Sobes.tech
Middle

Ispričaj mi o obrascu Factory.

sobes.tech АИ

Одговор од АИ

Фабрика — то је образац креирања који пружа општи интерфејс за креирање објеката у суперкласама, док подкласе могу мењати тип објеката које креирају.

  • Једноставна фабрика (Simple Factory): Није у потпуности образац, већ више идиома. Класа са методом која креира објекте на основу улазних параметара.

    package main
    
    import "fmt"
    
    type Product interface {
    	Use()
    }
    
    type ConcreteProductA struct{}
    
    func (p *ConcreteProductA) Use() {
    	fmt.Println("Користи Конкретан Производ А")
    }
    
    type ConcreteProductB struct{}
    
    func (p *ConcreteProductB) Use() {
    	fmt.Println("Користи Конкретан Производ Б")
    }
    
    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
    }
    
    // Конкретан производ А
    type ConcreteProduct1 struct{}
    
    func (p *ConcreteProduct1) Operation() string {
    	return "Резултат од Конкретног Производа 1"
    }
    
    // Конкретан производ Б
    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
    }
    
    // Конкретни креирач А
    type ConcreteCreator1 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator1) FactoryMethod() Product {
    	return &ConcreteProduct1{} // Креира Конкретан Производ А
    }
    
    // Конкретни креирач Б
    type ConcreteCreator2 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator2) FactoryMethod() Product {
    	return &ConcreteProduct2{} // Креира Конкретан Производ Б
    }
    
    func main() {
    	// Пример коришћења
    	creator1 := &ConcreteCreator1{}
    	fmt.Println(creator1.SomeOperation())
    
    	creator2 := &ConcreteCreator2{}
    	fmt.Println(creator2.SomeOperation())
    }
    
  • Апстрактна фабрика (Abstract Factory): Пружа интерфејс за креирање породице повезаних или зависних објеката без навођења њихових конкретних класа.

    package main
    
    import "fmt"
    
    // Интерфејс производа А
    type AbstractProductA interface {
    	UseProductA() string
    }
    
    // Конкретан производ А1
    type ConcreteProductA1 struct{}
    
    func (*ConcreteProductA1) UseProductA() string {
    	return "Резултат производа А1."
    }
    
    // Конкретан производ А2
    type ConcreteProductA2 struct{}
    
    func (*ConcreteProductA2) UseProductA() string {
    	return "Резултат производа А2."
    }
    
    // Интерфејс производа Б
    type AbstractProductB interface {
    	UseProductB() string
    	AnotherFunctionB(collaborator AbstractProductA) string // Взаимодејство са производом А
    }
    
    // Конкретан производ Б1
    type ConcreteProductB1 struct{}
    
    func (*ConcreteProductB1) UseProductB() string {
    	return "Резултат производа Б1."
    }
    
    // Взаимодејство Б1 са било којим типом AbstractProductA
    func (*ConcreteProductB1) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Резултат Б1 у сарадњи са (%s)", result)
    }
    
    // Конкретан производ Б2
    type ConcreteProductB2 struct{}
    
    func (*ConcreteProductB2) UseProductB() string {
    	return "Резултат производа Б2."
    }
    
    // Взаимодејство Б2 са било којим типом AbstractProductA
    func (*ConcreteProductB2) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Резултат Б2 у сарадњи са (%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{})
    }
    

Главна разлика између Фабричног метода и Апстрактне фабрике: Фабрички метод креира појединачне производе, док Апстрактна фабрика креира породице производа.

Назив образца Опис Када користити
Једноставна фабрика Метод у једној класи за креирање различитих типова објеката. За једноставно креирање објеката без потребе за хијерархијом фабрика.
Фабрички метод Интерфејс за креирање објекта, који омогућава подкласама да одлуче који ће класу инстанцирати. Када класа не може предвидети типове објеката које треба да креира.
Апстрактна фабрика Интерфејс за креирање породице повезаних објеката. Када систем треба да буде независан од начина креирања и представљања својих производа.

Образац Фабрика доприноси слабој повезаности кода и олакшава додавање нових типова производа без измене клиентског кода.