英文:
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()
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论