Sobes.tech
Middle

Разкажи ми за патърна Factory.

sobes.tech AI

Отговор от AI

Фабрика — това е порождащ патърн за дизайн, който предоставя общ интерфейс за създаване на обекти в суперкласата, докато подкласите могат да променят типа на създаваните обекти.

  • Проста фабрика (Simple Factory): Не е чист патърн, по-скоро идиома. Клас с метод, който създава обекти въз основа на входните параметри.

    package main
    
    import "fmt"
    
    type Product interface {
    	Use()
    }
    
    type ConcreteProductA struct{}
    
    func (p *ConcreteProductA) Use() {
    	fmt.Println("Използване на Concrete Product A")
    }
    
    type ConcreteProductB struct{}
    
    func (p *ConcreteProductB) Use() {
    	fmt.Println("Използване на Concrete Product B")
    }
    
    type SimpleFactory struct{}
    
    func (f *SimpleFactory) CreateProduct(t string) Product {
    	switch t {
    	case "A":
    		return &ConcreteProductA{}
    	case "B":
    		return &ConcreteProductB{}
    	default:
    		return nil
    	}
    }
    
    func main() {
    	factory := SimpleFactory{}
    	productA := factory.CreateProduct("A")
    	productA.Use()
    
    	productB := factory.CreateProduct("B")
    	productB.Use()
    }
    
  • Фабричен метод (Factory Method): Определя интерфейс за създаване на обект, но позволява на подкласите да решат кой клас да инстанцират.

    package main
    
    import "fmt"
    
    // Интерфейс на продукта
    type Product interface {
    	Operation() string
    }
    
    // Конкретен продукт A
    type ConcreteProduct1 struct{}
    
    func (p *ConcreteProduct1) Operation() string {
    	return "Резултат от ConcreteProduct1"
    }
    
    // Конкретен продукт B
    type ConcreteProduct2 struct{}
    
    func (p *ConcreteProduct2) Operation() string {
    	return "Резултат от ConcreteProduct2"
    }
    
    // Интерфейс на създателя
    type Creator interface {
    	FactoryMethod() Product
    	SomeOperation() string
    }
    
    // Базова структура на създателя
    type BaseCreator struct{}
    
    func (bc *BaseCreator) SomeOperation() string {
    	// Вика фабричния метод за получаване на обект продукт
    	product := bc.FactoryMethod()
    	// Използване на продукта
    	result := "Създавач: същият код на създателя току-що работи с " + product.Operation()
    	return result
    }
    
    // Конкретен създател A
    type ConcreteCreator1 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator1) FactoryMethod() Product {
    	return &ConcreteProduct1{} // Създава конкретен продукт A
    }
    
    // Конкретен създател B
    type ConcreteCreator2 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator2) FactoryMethod() Product {
    	return &ConcreteProduct2{} // Създава конкретен продукт B
    }
    
    func main() {
    	// Пример за използване
    	creator1 := &ConcreteCreator1{}
    	fmt.Println(creator1.SomeOperation())
    
    	creator2 := &ConcreteCreator2{}
    	fmt.Println(creator2.SomeOperation())
    }
    
  • Абстрактна фабрика (Abstract Factory): Предоставя интерфейс за създаване на семейства свързани или зависими обекти без да указва конкретните им класове.

    package main
    
    import "fmt"
    
    // Интерфейс на продукт A
    type AbstractProductA interface {
    	UseProductA() string
    }
    
    // Конкретен продукт A1
    type ConcreteProductA1 struct{}
    
    func (*ConcreteProductA1) UseProductA() string {
    	return "Резултат от продукт A1."
    }
    
    // Конкретен продукт A2
    type ConcreteProductA2 struct{}
    
    func (*ConcreteProductA2) UseProductA() string {
    	return "Резултат от продукт A2."
    }
    
    // Интерфейс на продукт B
    type AbstractProductB interface {
    	UseProductB() string
    	AnotherFunctionB(collaborator AbstractProductA) string // Взаимодействие с продукт A
    }
    
    // Конкретен продукт B1
    type ConcreteProductB1 struct{}
    
    func (*ConcreteProductB1) UseProductB() string {
    	return "Резултат от продукт B1."
    }
    
    func (*ConcreteProductB1) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Резултат от B1 сътрудничество с (%s)", result)
    }
    
    // Конкретен продукт B2
    type ConcreteProductB2 struct{}
    
    func (*ConcreteProductB2) UseProductB() string {
    	return "Резултат от продукт B2."
    }
    
    func (*ConcreteProductB2) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Резултат от B2 сътрудничество с (%s)", result)
    }
    
    // Интерфейс на абстрактната фабрика
    type AbstractFactory interface {
    	CreateProductA() AbstractProductA
    	CreateProductB() AbstractProductB
    }
    
    // Конкретна фабрика 1
    type ConcreteFactory1 struct{}
    
    func (*ConcreteFactory1) CreateProductA() AbstractProductA {
    	return &ConcreteProductA1{}
    }
    
    func (*ConcreteFactory1) CreateProductB() AbstractProductB {
    	return &ConcreteProductB1{}
    }
    
    // Конкретна фабрика 2
    type ConcreteFactory2 struct{}
    
    func (*ConcreteFactory2) CreateProductA() AbstractProductA {
    	return &ConcreteProductA2{}
    }
    
    func (*ConcreteFactory2) CreateProductB() AbstractProductB {
    	return &ConcreteProductB2{}
    }
    
    // Клиентски код, работещ с фабриката
    func ClientCode(factory AbstractFactory) {
    	productA := factory.CreateProductA()
    	productB := factory.CreateProductB()
    
    	fmt.Println(productB.UseProductB())
    	fmt.Println(productB.AnotherFunctionB(productA))
    }
    
    func main() {
    	fmt.Println("Клиент: Тестиране на клиентски код с първия тип фабрика:")
    	ClientCode(&ConcreteFactory1{})
    
    	fmt.Println("Клиент: Тестиране на същия клиентски код с втория тип фабрика:")
    	ClientCode(&ConcreteFactory2{})
    }
    

Основната разлика между Фабричния метод и Абстрактната фабрика: Фабричният метод създава единични продукти, докато Абстрактната фабрика създава семейства продукти.

Име на шаблона Описание Кога да го използваме
Простата фабрика Метод в един клас за създаване на обекти от различни типове. За простото създаване на обекти без необходимост от йерархия на фабрики.
Фабричен метод Интерфейс за създаване на обект, позволяващ на подкласите да решат кой клас да инстанцират. Когато класът не може да предвиди типа на обектите, които трябва да създаде.
Абстрактна фабрика Предоставя интерфейс за създаване на семейства свързани или зависими обекти без да указва конкретните им класове. Когато системата трябва да бъде независима от начина на създаване и представяне на продуктите.

Шаблонът фабрика насърчава слака свързаност на кода и улеснява добавянето на нови типове продукти без промяна в клиентския код.