Sobes.tech
Middle

Porozprávaj mi o vzore Factory.

sobes.tech AI

Odpoveď od AI

Fabrika je obrazec za kreiranje koji pruža opšti interfejs za pravljenje objekata u superklasama, dok podklase mogu menjati tip objekata koje kreiraju.

  • Jednostavna fabrika (Simple Factory): Nije u potpunosti obrazac, već više idiom. Klasa sa metodom koja kreira objekte na osnovu ulaznih parametara.

    package main
    
    import "fmt"
    
    type Product interface {
    	Use()
    }
    
    type ConcreteProductA struct{}
    
    func (p *ConcreteProductA) Use() {
    	fmt.Println("Korišćenje Konkretnog Proizvoda A")
    }
    
    type ConcreteProductB struct{}
    
    func (p *ConcreteProductB) Use() {
    	fmt.Println("Korišćenje Konkretnog Proizvoda 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
    }
    
    // Конкретан производ А
    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{})
    }
    

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

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

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