对于可能有数百个小类的情况,工厂模式的替代方案是什么?

huangapple go评论89阅读模式
英文:

Alternative to factory pattern for possibly hundreds of small classes

问题

我正在开发一个用Go语言编写的小游戏/模拟器,其中可能会有数百种技能。对于每个玩家,他们将拥有1到3个技能。我会将这些技能存储为字符串或ID。实例化这些技能的最佳方式是什么?通常我会使用工厂类,但考虑到我所说的数量,我不确定这是否是最佳方式。

英文:

I'm working on a small game/simulator, written in GoLang, in which there will be potentially hundreds of abilities. For each player, they will have between 1 and 3 abilities. I'll have these stored with either strings or Ids. What is the best way to instantiate these abilities. Normally I'd use a factory class, but with as many as I'm talking about, I'm not sure that's the best way.

答案1

得分: 6

你仍然可以使用工厂模式,就像encoding/gob包使用的那样。

例如,在abilities.go文件中,你可以这样定义:

type Ability interface {
	Execute()
}

var abilities = struct {
	m map[string]AbilityCtor
	sync.RWMutex
}{m: make(map[string]AbilityCtor)}

type AbilityCtor func() Ability

func Register(id string, newfunc AbilityCtor) {
	abilities.Lock()
	abilities.m[id] = newfunc
	abilities.Unlock()
}

func GetAbility(id string) (a Ability) {
	abilities.RLock()
	ctor, ok := abilities.m[id]
	abilities.RUnlock()
	if ok {
		a = ctor()
	}
	return
}

然后,对于每个能力(可能在单独的文件中),你可以这样做:

type Fireball struct{}

func (s *Fireball) Execute() {
	fmt.Println("FIREBALL EXECUTED")
}

func init() {
	Register("Fireball", func() Ability {
		return &Fireball{}
	})
}

func main() {
	if fireball := GetAbility("Fireball"); fireball != nil { //如果未找到可能为nil
		fireball.Execute()
	}
}
英文:

You can still use the factory pattern, it's what the encoding/gob package uses.

playground: http://play.golang.org/p/LjR4PTTCvw

For example in abilities.go you could have

type Ability interface {
	Execute()
}

var abilities = struct {
	m map[string]AbilityCtor
	sync.RWMutex
}{m: make(map[string]AbilityCtor)}

type AbilityCtor func() Ability

func Register(id string, newfunc AbilityCtor) {
	abilities.Lock()
	abilities.m[id] = newfunc
	abilities.Unlock()
}

func GetAbility(id string) (a Ability) {
	abilities.RLock()
	ctor, ok := abilities.m[id]
	abilities.RUnlock()
	if ok {
		a = ctor()
	}
	return
}

Then for each ability (in separate files probably) you could do something like :

type Fireball struct{}

func (s *Fireball) Execute() {
	fmt.Println("FIREBALL EXECUTED")
}

func init() {
	Register("Fireball", func() Ability {
		return &Fireball{}
	})
}

func main() {
	if fireball := GetAbility("Fireball"); fireball != nil { //could be nil if not found
		fireball.Execute()
	}
}

huangapple
  • 本文由 发表于 2014年6月10日 11:57:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/24132594.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定