
import (
"fmt"
)
//ProductA is abstract product A
type ProductA interface {
TestA()
}
//ProductB is abstract product B
type ProductB interface {
TestB()
}
//Factory is abstract factory
type Factory interface {
CreateA() ProductA
CreateB() ProductB
}
//ProductA1 is concrete product A1
type ProductA1 struct{}
//TestA is implementation of the ProductA interface method
func (p ProductA1) TestA() {
fmt.Println("test A1")
}
//ProductB1 is concrete product B1
type ProductB1 struct{}
//TestB is implementation of the ProductB interface method
func (p ProductB1) TestB() {
fmt.Println("test B1")
}
//ProductA2 is concrete product A2
type ProductA2 struct{}
//TestA is implementation of the ProductA interface method
func (p ProductA2) TestA() {
fmt.Println("test A2")
}
//ProductB2 is concrete product B2
type ProductB2 struct{}
//TestB is implementation of the ProductB interface method
func (p ProductB2) TestB() {
fmt.Println("test B2")
}
//Factory1 is concrete factory 1
type Factory1 struct{}
//CreateA is implementation of the Factory interface method
func (f Factory1) CreateA() ProductA {
return ProductA1{}
}
//CreateB is implementation of the Factory interface method
func (f Factory1) CreateB() ProductB {
return ProductB1{}
}
//Factory2 is concrete factory 2
type Factory2 struct{}
//CreateA is implementation of the Factory interface method
func (f Factory2) CreateA() ProductA {
return ProductA2{}
}
//CreateB is implementation of the Factory interface method
func (f Factory2) CreateB() ProductB {
return ProductB2{}
}
//client code:
//TestFactory creates and tests factories
func TestFactory(factory Factory) {
productA := factory.CreateA()
productB := factory.CreateB()
productA.TestA()
productB.TestB()
}
TestFactory(Factory1{})
//printed: test A1
// test B1
TestFactory(Factory2{})
//printed: test A2
// test B2
Предоставляет интерфейс для создания семейств объектов, интерфейсы которых известны, а конкретные классы нет.Read moreЗадача. Программа рисует окна в двух стилях, светлом и тёмном. Каждому стилю нужны своя кнопка и своё меню. Если код создаёт их напрямую, он может по ошибке соединить светлую кнопку с тёмным меню. А третий стиль заставит искать каждое место, где создаётся кнопка или меню. Идея. Абстрактная фабрика - это интерфейс, в котором на каждый вид продукта есть свой метод создания. Каждая конкретная фабрика реализует его для одного семейства. Одна фабрика создаёт светлые кнопку и меню, другая - тёмные. Клиент получает фабрику и создаёт через неё все продукты. Конкретный продукт он никогда не называет, поэтому всё, что он получает, принадлежит одному семейству. Чтобы сменить семейство целиком, клиенту дают другую фабрику. Как читать пример. Продукты бывают двух видов, A и B. Конкретная фабрика выпускает одно семейство: по одному продукту каждого вида, и у обоих один и тот же номер. Клиент получает фабрику, просит у неё по продукту каждого вида и пользуется обоими. Какое семейство ему досталось, клиент не знает, но вывод это показывает. В некоторых языках интерфейсов не объявляют вовсе, но роли остаются теми же. Когда применять. Абстрактная фабрика нужна, когда продукты должны работать вместе и у них несколько семейств, как у тем оформления или операционных систем. При одном семействе она ни к чему. Не нужна она и тогда, когда продукты друг от друга не зависят: хватит конструктора или Фабричного метода. Частая ошибка. Взять этот паттерн, пока виды продуктов ещё часто меняются. Каждый новый вид добавляет метод и в абстрактную фабрику, и в каждую конкретную. |