Шаблон "Фабрика" - это порождающий шаблон проектирования, а также один из наиболее часто используемых шаблонов. Этот шаблон позволяет скрыть логику создания генерируемых экземпляров.
Клиент взаимодействует только с фабричной структурой и сообщает, какие экземпляры необходимо создать. Класс фабрики взаимодействует с соответствующими конкретными структурами и возвращает правильный экземпляр.
В приведенном ниже примере:
- у нас есть интерфейс
Gun
, определяющий все методы, которые должны быть у автоматического оружия. Существует структураgun
, которая реализует интерфейсGun
. - две конкретных реализации -
ak47
иmaverick
. В обе встроена структураgun
и, следовательно, оба неявно реализуют все методыGun
и отсюдаGun
типа. - существует структура
gunFactory
, которая создаёт автоматическое оружие типаak47
иmaverick
. main.go
здесь является клиентом и вместо непосредственно генерацииak47
илиmaverick
, он полагается наgunFactory
, которая создаёт экземплярыak47
иmaverick
.
Ниже приведена соответствующая UML диаграмма для примера, описанного выше.
В таблице представлено соответствие между актёрами на UML диаграмме и файлами из примера.
Актёр на UML диаграмме | Файл из примера |
---|---|
ProductFactory | gun/factory.go |
iProduct | interfaces/gun.go |
Product | gun/common.go |
Concrete Product 1 | gun/ak47.go |
Concrete Product 2 | gun/maverick.go |
Client | main.go |
interfaces/gun.go
type Gun interface {
SetName(name string)
SetPower(power int)
GetName() string
GetPower() int
}
gun/common.go
type gun struct {
name string
power int
}
func (g *gun) SetName(name string) {
g.name = name
}
func (g *gun) GetName() string {
return g.name
}
func (g *gun) SetPower(power int) {
g.power = power
}
func (g *gun) GetPower() int {
return g.power
}
gun/ak47.go
type ak47 struct {
gun
}
func NewAk47() interfaces.Gun {
return &ak47{
gun: gun{
name: "AK47 gun",
power: 4,
},
}
}
gun/maverick.go
type maverick struct {
gun
}
func NewMaverick() interfaces.Gun {
return &maverick{
gun: gun{
name: "Maverick gun",
power: 5,
},
}
}
gun/factory.go
func GetGun(gunType string) (interfaces.Gun, error) {
if gunType == "ak47" {
return NewAk47(), nil
}
if gunType == "maverick" {
return NewMaverick(), nil
}
return nil, errors.New("wrong gun type passed")
}
main.go
func main() {
ak47, err := gun.GetGun("ak47")
if err != nil {
log.Fatalf("Cannot create ak47 gun. Error %v", err)
}
maverick, err := gun.GetGun("maverick")
if err != nil {
log.Fatalf("Cannot create maverick gun. Error %v", err)
}
printDetails(ak47)
printDetails(maverick)
}
func printDetails(g interfaces.Gun) {
fmt.Printf("Gun: %s\n", g.GetName())
fmt.Printf("Power: %d\n", g.GetPower())
}
Результат в терминале:
go run main.go
Gun: AK47 gun
Power: 4
Gun: Maverick gun
Power: 5