Sobes.tech
Middle

Vorbește despre pattern-ul Factory.

sobes.tech AI

Răspuns de la AI

Fabrica este un pattern de creare care oferă o interfață comună pentru crearea obiectelor în superclasă, în timp ce subclasele pot modifica tipul obiectelor create.

  • Fabrica Simplă (Simple Factory): Nu este un pattern în sensul pur, ci mai degrabă un idiom. O clasă cu o metodă care creează obiecte pe baza parametrilor de intrare.

    package main
    
    import "fmt"
    
    type Product interface {
    	Use()
    }
    
    type ConcreteProductA struct{}
    
    func (p *ConcreteProductA) Use() {
    	fmt.Println("Utilizarea produsului Concrete A")
    }
    
    type ConcreteProductB struct{}
    
    func (p *ConcreteProductB) Use() {
    	fmt.Println("Utilizarea produsului Concrete 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()
    }
    
  • Metoda Fabrica (Factory Method): Definează o interfață pentru crearea unui obiect, dar permite subclasei să decidă ce clasă să instanțieze.

    package main
    
    import "fmt"
    
    // Interfața produsului
    type Product interface {
    	Operation() string
    }
    
    // Produsul concret A
    type ConcreteProduct1 struct{}
    
    func (p *ConcreteProduct1) Operation() string {
    	return "Rezultatul ConcreteProduct1"
    }
    
    // Produsul concret B
    type ConcreteProduct2 struct{}
    
    func (p *ConcreteProduct2) Operation() string {
    	return "Rezultatul ConcreteProduct2"
    }
    
    // Interfața creatorului
    type Creator interface {
    	FactoryMethod() Product
    	SomeOperation() string
    }
    
    // Structura de bază a creatorului
    type BaseCreator struct{}
    
    func (bc *BaseCreator) SomeOperation() string {
    	// Apelarea metodei factory pentru a obține obiectul produs
    	product := bc.FactoryMethod()
    	// Utilizarea produsului
    	result := "Creator: Același cod al creatorului a lucrat chiar cu " + product.Operation()
    	return result
    }
    
    // Creatorul concret A
    type ConcreteCreator1 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator1) FactoryMethod() Product {
    	return &ConcreteProduct1{} // Creează produsul concret A
    }
    
    // Creatorul concret B
    type ConcreteCreator2 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator2) FactoryMethod() Product {
    	return &ConcreteProduct2{} // Creează produsul concret B
    }
    
    func main() {
    	// Exemplu de utilizare
    	creator1 := &ConcreteCreator1{}
    	fmt.Println(creator1.SomeOperation())
    
    	creator2 := &ConcreteCreator2{}
    	fmt.Println(creator2.SomeOperation())
    }
    
  • Fabrica abstractă (Abstract Factory): Oferă o interfață pentru crearea familiilor de obiecte legate sau dependente fără a specifica clasele lor concrete.

    package main
    
    import "fmt"
    
    // Interfața produsului A
    type AbstractProductA interface {
    	UseProductA() string
    }
    
    // Produsul A1 concret
    type ConcreteProductA1 struct{}
    
    func (*ConcreteProductA1) UseProductA() string {
    	return "Rezultatul produsului A1."
    }
    
    // Produsul A2 concret
    type ConcreteProductA2 struct{}
    
    func (*ConcreteProductA2) UseProductA() string {
    	return "Rezultatul produsului A2."
    }
    
    // Interfața produsului B
    type AbstractProductB interface {
    	UseProductB() string
    	AnotherFunctionB(collaborator AbstractProductA) string // Interacțiune cu produsul A
    }
    
    // Produsul B1 concret
    type ConcreteProductB1 struct{}
    
    func (*ConcreteProductB1) UseProductB() string {
    	return "Rezultatul produsului B1."
    }
    
    // Interacțiunea B1 cu orice tip de AbstractProductA
    func (*ConcreteProductB1) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Rezultatul B1 colaborând cu (%s)", result)
    }
    
    // Produsul B2 concret
    type ConcreteProductB2 struct{}
    
    func (*ConcreteProductB2) UseProductB() string {
    	return "Rezultatul produsului B2."
    }
    
    // Interacțiunea B2 cu orice tip de AbstractProductA
    func (*ConcreteProductB2) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Rezultatul B2 colaborând cu (%s)", result)
    }
    
    // Interfața fabricii abstracte
    type AbstractFactory interface {
    	CreateProductA() AbstractProductA
    	CreateProductB() AbstractProductB
    }
    
    // Fabrica concretă 1
    type ConcreteFactory1 struct{}
    
    func (*ConcreteFactory1) CreateProductA() AbstractProductA {
    	return &ConcreteProductA1{}
    }
    
    func (*ConcreteFactory1) CreateProductB() AbstractProductB {
    	return &ConcreteProductB1{}
    }
    
    // Fabrica concretă 2
    type ConcreteFactory2 struct{}
    
    func (*ConcreteFactory2) CreateProductA() AbstractProductA {
    	return &ConcreteProductA2{}
    }
    
    func (*ConcreteFactory2) CreateProductB() AbstractProductB {
    	return &ConcreteProductB2{}
    }
    
    // Codul client care lucrează cu fabrica
    func ClientCode(factory AbstractFactory) {
    	productA := factory.CreateProductA()
    	productB := factory.CreateProductB()
    
    	fmt.Println(productB.UseProductB())
    	fmt.Println(productB.AnotherFunctionB(productA))
    }
    
    func main() {
    	fmt.Println("Client: Testarea codului client cu primul tip de fabrică:")
    	ClientCode(&ConcreteFactory1{})
    
    	fmt.Println("Client: Testarea aceluiași cod client cu al doilea tip de fabrică:")
    	ClientCode(&ConcreteFactory2{})
    }
    

Principala diferență între Factory Method și Abstract Factory: Factory Method creează produse individuale, în timp ce Abstract Factory creează familii de produse.

Numele pattern-ului Descriere Când să îl folosiți
Fabrica Simplă Metoda într-o clasă pentru crearea obiectelor de diferite tipuri. Pentru crearea simplă de obiecte fără necesitatea unei ierarhii de fabrici.
Factory Method Interfață pentru crearea unui obiect, permițând subclasei să decidă ce clasă să instanțieze. Când o clasă nu poate prezice tipul de obiecte pe care trebuie să le creeze.
Fabrica Abstractă Interfață pentru crearea familiilor de obiecte legate sau dependente. Când sistemul trebuie să fie independent de modul în care sunt create și prezentate produsele sale.

Pattern-ul Fabrica contribuie la reducerea cuplajului codului și facilitează adăugarea de noi tipuri de produse fără a modifica codul clientului.