Opowiedz o wzorcu Factory.
sobes.tech AI
Odpowiedź od AI
Fabrika to wzorzec projektowy tworzenia, który zapewnia wspólny interfejs do tworzenia obiektów w superklasie, podczas gdy podklasy mogą zmieniać typ tworzonych obiektów.
-
Prosta fabryka (Simple Factory): Nie jest to wzorzec w czystej formie, raczej idiom. Klasa z metodą tworzącą obiekty na podstawie parametrów wejściowych.
package main import "fmt" type Product interface { Use() } type ConcreteProductA struct{} func (p *ConcreteProductA) Use() { fmt.Println("Używanie produktu Concrete A") } type ConcreteProductB struct{} func (p *ConcreteProductB) Use() { fmt.Println("Używanie produktu 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 fabryczna (Factory Method): Definiuje interfejs do tworzenia obiektu, ale pozwala podklasom decydować, którą klasę zainstancjonować.
package main import "fmt" // Interfejs produktu type Product interface { Operation() string } // Konkretne produkty A type ConcreteProduct1 struct{} func (p *ConcreteProduct1) Operation() string { return "Wynik ConcreteProduct1" } // Konkretne produkty B type ConcreteProduct2 struct{} func (p *ConcreteProduct2) Operation() string { return "Wynik ConcreteProduct2" } // Interfejs twórcy type Creator interface { FactoryMethod() Product SomeOperation() string } // Podstawowa struktura twórcy type BaseCreator struct{} func (bc *BaseCreator) SomeOperation() string { // Wywołanie metody fabrycznej w celu uzyskania obiektu produktu product := bc.FactoryMethod() // Użycie produktu result := "Twórca: Ten sam kod twórcy właśnie pracował z " + product.Operation() return result } // Konkretni twórcy type ConcreteCreator1 struct { BaseCreator } func (cc *ConcreteCreator1) FactoryMethod() Product { return &ConcreteProduct1{} // Tworzy konkretny produkt A } type ConcreteCreator2 struct { BaseCreator } func (cc *ConcreteCreator2) FactoryMethod() Product { return &ConcreteProduct2{} // Tworzy konkretny produkt B } func main() { // Przykład użycia creator1 := &ConcreteCreator1{} fmt.Println(creator1.SomeOperation()) creator2 := &ConcreteCreator2{} fmt.Println(creator2.SomeOperation()) } -
Fabrika abstrakcyjna (Abstract Factory): Zapewnia interfejs do tworzenia rodzin powiązanych lub zależnych obiektów bez wskazywania ich konkretnych klas.
package main import "fmt" // Interfejs produktu A type AbstractProductA interface { UseProductA() string } // Konkretne produkty A1 type ConcreteProductA1 struct{} func (*ConcreteProductA1) UseProductA() string { return "Wynik produktu A1." } // Konkretne produkty A2 type ConcreteProductA2 struct{} func (*ConcreteProductA2) UseProductA() string { return "Wynik produktu A2." } // Interfejs produktu B type AbstractProductB interface { UseProductB() string AnotherFunctionB(collaborator AbstractProductA) string // Interakcja z produktem A } // Konkretne produkty B1 type ConcreteProductB1 struct{} func (*ConcreteProductB1) UseProductB() string { return "Wynik produktu B1." } // Interakcja B1 z dowolnym typem AbstractProductA func (*ConcreteProductB1) AnotherFunctionB(collaborator AbstractProductA) string { result := collaborator.UseProductA() return fmt.Sprintf("Wynik B1 współpracującego z (%s)", result) } // Konkretne produkty B2 type ConcreteProductB2 struct{} func (*ConcreteProductB2) UseProductB() string { return "Wynik produktu B2." } // Interakcja B2 z dowolnym typem AbstractProductA func (*ConcreteProductB2) AnotherFunctionB(collaborator AbstractProductA) string { result := collaborator.UseProductA() return fmt.Sprintf("Wynik B2 współpracującego z (%s)", result) } // Interfejs fabryki abstrakcyjnej type AbstractFactory interface { CreateProductA() AbstractProductA CreateProductB() AbstractProductB } // Konkretna fabryka 1 type ConcreteFactory1 struct{} func (*ConcreteFactory1) CreateProductA() AbstractProductA { return &ConcreteProductA1{} } func (*ConcreteFactory1) CreateProductB() AbstractProductB { return &ConcreteProductB1{} } // Konkretna fabryka 2 type ConcreteFactory2 struct{} func (*ConcreteFactory2) CreateProductA() AbstractProductA { return &ConcreteProductA2{} } func (*ConcreteFactory2) CreateProductB() AbstractProductB { return &ConcreteProductB2{} } // Kod klienta pracujący z fabryką func ClientCode(factory AbstractFactory) { productA := factory.CreateProductA() productB := factory.CreateProductB() fmt.Println(productB.UseProductB()) fmt.Println(productB.AnotherFunctionB(productA)) } func main() { fmt.Println("Klient: Testowanie kodu klienta z pierwszym typem fabryki:") ClientCode(&ConcreteFactory1{}) fmt.Println("Klient: Testowanie tego samego kodu klienta z drugim typem fabryki:") ClientCode(&ConcreteFactory2{}) }
Główna różnica między Factory Method a Abstract Factory: Factory Method tworzy pojedyncze produkty, podczas gdy Abstract Factory tworzy rodziny produktów.
| Nazwa wzorca | Opis | Kiedy go używać |
|---|---|---|
| Prosta fabryka | Metoda w jednej klasie do tworzenia obiektów różnych typów. | Do prostego tworzenia obiektów bez konieczności hierarchii fabryk. |
| Metoda fabryczna | Interfejs do tworzenia obiektu, pozwalający podklasom decydować, którą klasę zainstancjonować. | Gdy klasa nie może przewidzieć typu obiektów, które musi utworzyć. |
| Fabryka abstrakcyjna | Interfejs do tworzenia powiązanych rodzin obiektów. | Gdy system musi być niezależny od sposobu tworzenia i reprezentacji jego produktów. |
Wzorzec fabryki sprzyja luźnemu powiązaniu kodu i ułatwia dodawanie nowych typów produktów bez zmiany kodu klienta.