Это паттерн создания, который позволяет нам создать «фабрику» объектов из базового класса и реализовать полиморфное поведение, которое позволяет нам изменять поведение наследуемых классов.
Обычно он используется для повторного использования логики создания, разделяющей ряд объектов.
Go не является строго объектно-ориентированным языком, но мы можем реализовать логику ООП через интерфейсы и концепцию композиции над наследованием.
Пример
У нас есть серия продуктов (объектов), которые ведут себя одинаково. Мы можем либо создать отдельный класс для каждого из них, либо поместить всю эту логику в базовый класс, чтобы создать наследуемые классы для каждого продукта.
- Сначала нам нужно определить интерфейс, который описывает поведение наших продуктов, «сделанных» на нашей «фабрике».
type IProduct interface {
setStock(stock int)
getStock() int
setName(name string)
getName() string
}
- Определите, как выглядит наш продукт, затем реализуйте методы IProduct, чтобы соответствовать интерфейсу. Это похоже на определение абстрактного класса.
type Computer struct {
name string
stock int
}
func (c *Computer) setStock(stock int) {
c.stock = stock
}
func (c *Computer) getStock() int {
return c.stock
}
func (c *Computer) setName(name string) {
c.name = name
}
func (c *Computer) getName() string {
return c.name
}
- Создайте классы наших продуктов, которые наследуются от класса Computer. Здесь применяется концепция композиции над наследованием.
type Laptop struct {
Computer
}
func newLaptop() IProduct {
return &Laptop{
Computer: Computer{
name: "Laptop Computer",
stock: 0,
},
}
}
type Desktop struct {
Computer
}
func newDesktop() IProduct {
return &Desktop{
Computer: Computer{
name: "Desktop Computer",
stock: 0,
},
}
}
- Наконец, нам нужно «создать» наш метод фабрики, этот метод будет возвращать экземпляр указанного объекта.
func GetComputerFactory(computerType string) (IProduct, error) {
if computerType == "laptop" {
return newLaptop(), nil
} else if computerType == "desktop" {
return newDesktop(), nil
} else {
return nil, fmt.Errorf("invalid computer type")
}
}
Запуск нашего кода
func PrintNameAndStock(p IProduct) {
fmt.Printf("Product name: %s, with stock %dn", p.getName(), p.getStock())
}
func main() {
laptop, _ := GetComputerFactory("laptop")
desktop, _ := GetComputerFactory("desktop")
laptop.setStock(10)
PrintNameAndStock(laptop)
desktop.setStock(20)
PrintNameAndStock(desktop)
}
Вывод
Product name: Laptop Computer, with stock 10
Product name: Desktop Computer, with stock 20
Пример полного экрана
package main
import "fmt"
type IProduct interface {
setStock(stock int)
getStock() int
setName(name string)
getName() string
}
type Computer struct {
name string
stock int
}
func (c *Computer) setStock(stock int) {
c.stock = stock
}
func (c *Computer) getStock() int {
return c.stock
}
func (c *Computer) setName(name string) {
c.name = name
}
func (c *Computer) getName() string {
return c.name
}
type Laptop struct {
Computer
}
func newLaptop() IProduct {
return &Laptop{
Computer: Computer{
name: "Laptop Computer",
stock: 0,
},
}
}
type Desktop struct {
Computer
}
func newDesktop() IProduct {
return &Desktop{
Computer: Computer{
name: "Desktop Computer",
stock: 0,
},
}
}
func GetComputerFactory(computerType string) (IProduct, error) {
if computerType == "laptop" {
return newLaptop(), nil
} else if computerType == "desktop" {
return newDesktop(), nil
} else {
return nil, fmt.Errorf("invalid computer type")
}
}
func PrintNameAndStock(p IProduct) {
fmt.Printf("Product name: %s, with stock %dn", p.getName(), p.getStock())
}
func main() {
laptop, _ := GetComputerFactory("laptop")
desktop, _ := GetComputerFactory("desktop")
laptop.setStock(10)
PrintNameAndStock(laptop)
desktop.setStock(20)
PrintNameAndStock(desktop)
}
Надеюсь, я вам помог 😊😊😊