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("Использование Конкретного продукта A")
    }
    
    type ConcreteProductB struct{}
    
    func (p *ConcreteProductB) Use() {
    	fmt.Println("Использование Конкретного продукта 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 "Результат от Конкретного продукта 1"
    }
    
    // Конкретный продукт B
    type ConcreteProduct2 struct{}
    
    func (p *ConcreteProduct2) Operation() string {
    	return "Результат от Конкретного продукта 2"
    }
    
    // Интерфейс создателя
    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."
    }
    
    // Взаимодействие B1 с любым типом AbstractProductA
    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."
    }
    
    // Взаимодействие B2 с любым типом AbstractProductA
    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{})
    }
    

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

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

Паттерн Фабрика способствует слабой связанности кода и облегчает добавление новых типов продуктов без изменения клиентского кода.