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."
    }
    
    // Взаимодействие 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{})
    }
    

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

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

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