
Абстрактна фабрика на Go
Абстрактна фабрика — це породжуючий патерн проектування, який вирішує проблему створення цілих сімейств пов’язаних продуктів, без прив’язки коду до конкретних класів продуктів.
Абстрактна фабрика задає інтерфейс створення всіх доступних типів продуктів, а кожна конкретна реалізація фабрики породжує продукти однієї з варіацій. Клієнтський код викликає методи фабрики для отримання продуктів, замість самостійного створювання їх за допомогою оператора new
. При цьому, фабрика сама стежить за тим, щоб створюваний продукт був потрібної варіації.
Концептуальний приклад
Уявімо, що вам потрібно купити спортивну форму, яка складається з двох різних речей: пара взуття і футболка. Ви хочете придбати повний комплект від одного бренду, щоб речі поєднувалися між собою.
Перекладаючи вищевказане у код, Абстрактна фабрика допоможе нам створювати набори продуктів, які завжди будуть підходити один до одного.
iSportsFactory.go: Інтерфейс абстрактної фабрики
package main
import "fmt"
type iSportsFactory interface {
makeShoe() iShoe
makeShirt() iShirt
}
func getSportsFactory(brand string) (iSportsFactory, error) {
if brand == "adidas" {
return &adidas{}, nil
}
if brand == "nike" {
return &nike{}, nil
}
return nil, fmt.Errorf("Wrong brand type passed")
}
adidas.go: Конкретна фабрика
package main
type adidas struct {
}
func (a *adidas) makeShoe() iShoe {
return &adidasShoe{
shoe: shoe{
logo: "adidas",
size: 14,
},
}
}
func (a *adidas) makeShirt() iShirt {
return &adidasShirt{
shirt: shirt{
logo: "adidas",
size: 14,
},
}
}
nike.go: Конкретна фабрика
package main
type nike struct {
}
func (n *nike) makeShoe() iShoe {
return &nikeShoe{
shoe: shoe{
logo: "nike",
size: 14,
},
}
}
func (n *nike) makeShirt() iShirt {
return &nikeShirt{
shirt: shirt{
logo: "nike",
size: 14,
},
}
}
iShoe.go: Абстрактний продукт
package main
type iShoe interface {
setLogo(logo string)
setSize(size int)
getLogo() string
getSize() int
}
type shoe struct {
logo string
size int
}
func (s *shoe) setLogo(logo string) {
s.logo = logo
}
func (s *shoe) getLogo() string {
return s.logo
}
func (s *shoe) setSize(size int) {
s.size = size
}
func (s *shoe) getSize() int {
return s.size
}
adidasShoe.go: Конкретний продукт
package main
type adidasShoe struct {
shoe
}
nikeShoe.go: Конкретний продукт
package main
type nikeShoe struct {
shoe
}
iShirt.go: Абстрактний продукт
package main
type iShirt interface {
setLogo(logo string)
setSize(size int)
getLogo() string
getSize() int
}
type shirt struct {
logo string
size int
}
func (s *shirt) setLogo(logo string) {
s.logo = logo
}
func (s *shirt) getLogo() string {
return s.logo
}
func (s *shirt) setSize(size int) {
s.size = size
}
func (s *shirt) getSize() int {
return s.size
}
adidasShirt.go: Конкретний продукт
package main
type adidasShirt struct {
shirt
}
nikeShirt.go: Конкретний продукт
package main
type nikeShirt struct {
shirt
}
main.go: Клієнтський код
package main
import "fmt"
func main() {
adidasFactory, _ := getSportsFactory("adidas")
nikeFactory, _ := getSportsFactory("nike")
nikeShoe := nikeFactory.makeShoe()
nikeShirt := nikeFactory.makeShirt()
adidasShoe := adidasFactory.makeShoe()
adidasShirt := adidasFactory.makeShirt()
printShoeDetails(nikeShoe)
printShirtDetails(nikeShirt)
printShoeDetails(adidasShoe)
printShirtDetails(adidasShirt)
}
func printShoeDetails(s iShoe) {
fmt.Printf("Logo: %s", s.getLogo())
fmt.Println()
fmt.Printf("Size: %d", s.getSize())
fmt.Println()
}
func printShirtDetails(s iShirt) {
fmt.Printf("Logo: %s", s.getLogo())
fmt.Println()
fmt.Printf("Size: %d", s.getSize())
fmt.Println()
}
output.txt: Результат виконання
Logo: nike
Size: 14
Logo: nike
Size: 14
Logo: adidas
Size: 14
Logo: adidas
Size: 14