Creational pattern - Abstract Factory
Use cases:
- when you need to work with related classes while decoupling it on concrete classes
- Consumer of your factory can easily use your factory methods and do not worry about compatibility of objects from different sub types
Example:
Define iShirt and shirt
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package abstract_factory
type iShirt interface { Size() int SetSize(size int) Logo() string SetLogo(logo string) }
type shirt struct { logo string size int }
func (s *shirt) SetLogo(logo string) { s.logo = logo } func (s *shirt) Logo() string { return s.logo } func (s *shirt) SetSize(size int) { s.size = size } func (s *shirt) Size() int { return s.size }
|
Define iShoe and shoe
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package abstract_factory
type shoe struct { logo string size int } type iShoe interface { Size() int SetSize(size int) Logo() string SetLogo(logo string) }
func (s *shoe) SetLogo(logo string) { s.logo = logo } func (s *shoe) Logo() string { return s.logo } func (s *shoe) SetSize(size int) { s.size = size } func (s *shoe) Size() int { return s.size }
|
Define concretenike
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package abstract_factory
type nike struct{}
type nikeShirt struct { shirt } type nikeShoe struct { shoe }
func (n *nike) Shoe() iShoe { return &nikeShoe{shoe: shoe{logo: "Nike", size: 10}} } func (n *nike) Shirt() iShirt { return &nikeShirt{shirt: shirt{logo: "Nike", size: 20}} }
|
Define concreteadidas
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package abstract_factory
type adidasShirt struct { shirt } type adidasShoe struct { shoe }
type adidas struct{}
func (n *adidas) Shoe() iShoe { return &adidasShoe{shoe: shoe{logo: "Adidas", size: 14}} } func (n *adidas) Shirt() iShirt { return &adidasShirt{shirt: shirt{logo: "Adidas", size: 30}} }
|
Define iWearFactory
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package abstract_factory
type iWearFactory interface { Shoe() iShoe Shirt() iShirt }
type Brands int
const ( Nike Brands = iota Adidas )
func NewWearFactory(brand Brands) iWearFactory { switch brand { case Nike: return &nike{} case Adidas: return &adidas{} } return nil }
|
Simple usage:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| func main() { adidasFactory := abstract_factory.NewWearFactory(abstract_factory.Adidas) nikeFactory := abstract_factory.NewWearFactory(abstract_factory.Nike)
shoe1 := nikeFactory.Shoe() shirt1 := nikeFactory.Shirt() shoe2 := adidasFactory.Shoe() shirt2 := adidasFactory.Shirt() fmt.Printf("%v \n", shoe1) fmt.Printf("%v \n", shoe2) fmt.Printf("%v \n", shirt1) fmt.Printf("%v \n", shirt2) }
|