Search code examples
design-patternsgofactory-pattern

Alternative to factory pattern for possibly hundreds of small classes


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.


Solution

  • 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()
        }
    }