Sobes.tech
Middle

Erzählen Sie mir vom Factory-Pattern.

sobes.tech KI

Antwort von AI

Fabrik ist ein creational Pattern, das eine gemeinsame Schnittstelle für die Erstellung von Objekten in der Superklasse bereitstellt, während Unterklassen den Typ der erstellten Objekte ändern können.

  • Einfache Fabrik (Simple Factory): Kein reines Pattern, sondern eher eine Idiomatik. Eine Klasse mit einer Methode, die Objekte basierend auf den Eingabeparametern erstellt.

    package main
    
    import "fmt"
    
    type Product interface {
    	Use()
    }
    
    type ConcreteProductA struct{}
    
    func (p *ConcreteProductA) Use() {
    	fmt.Println("Verwende Concrete Product A")
    }
    
    type ConcreteProductB struct{}
    
    func (p *ConcreteProductB) Use() {
    	fmt.Println("Verwende 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()
    }
    
  • Fabrikmethode (Factory Method): Definiert eine Schnittstelle zur Objekterstellung, lässt aber Unterklassen entscheiden, welche Klasse instanziiert wird.

    package main
    
    import "fmt"
    
    // Produkt-Interface
    type Product interface {
    	Operation() string
    }
    
    // Konkretes Produkt A
    type ConcreteProduct1 struct{}
    
    func (p *ConcreteProduct1) Operation() string {
    	return "Ergebnis des ConcreteProduct1"
    }
    
    // Konkretes Produkt B
    type ConcreteProduct2 struct{}
    
    func (p *ConcreteProduct2) Operation() string {
    	return "Ergebnis des ConcreteProduct2"
    }
    
    // Creator-Interface
    type Creator interface {
    	FactoryMethod() Product
    	SomeOperation() string
    }
    
    // Basisklasse des Erstellers
    type BaseCreator struct{}
    
    func (bc *BaseCreator) SomeOperation() string {
    	// Aufruf der Fabrikmethode zur Erzeugung eines Produkt-Objekts
    	product := bc.FactoryMethod()
    	// Verwendung des Produkts
    	result := "Der Erzeuger hat gerade mit " + product.Operation() + " gearbeitet"
    	return result
    }
    
    // Konkreter Erzeuger A
    type ConcreteCreator1 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator1) FactoryMethod() Product {
    	return &ConcreteProduct1{} // Erzeugt konkretes Produkt A
    }
    
    // Konkreter Erzeuger B
    type ConcreteCreator2 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator2) FactoryMethod() Product {
    	return &ConcreteProduct2{} // Erzeugt konkretes Produkt B
    }
    
    func main() {
    	// Beispiel
    	creator1 := &ConcreteCreator1{}
    	fmt.Println(creator1.SomeOperation())
    
    	creator2 := &ConcreteCreator2{}
    	fmt.Println(creator2.SomeOperation())
    }
    
  • Abstrakte Fabrik (Abstract Factory): Bietet eine Schnittstelle zur Erstellung von Familien verwandter oder abhängiger Objekte, ohne ihre konkreten Klassen anzugeben.

    package main
    
    import "fmt"
    
    // Schnittstelle für Produkt A
    type AbstractProductA interface {
    	UseProductA() string
    }
    
    // Konkretes Produkt A1
    type ConcreteProductA1 struct{}
    
    func (*ConcreteProductA1) UseProductA() string {
    	return "Das Ergebnis des Produkts A1."
    }
    
    // Konkretes Produkt A2
    type ConcreteProductA2 struct{}
    
    func (*ConcreteProductA2) UseProductA() string {
    	return "Das Ergebnis des Produkts A2."
    }
    
    // Schnittstelle für Produkt B
    type AbstractProductB interface {
    	UseProductB() string
    	AnotherFunctionB(collaborator AbstractProductA) string // Interaktion mit Produkt A
    }
    
    // Konkretes Produkt B1
    type ConcreteProductB1 struct{}
    
    func (*ConcreteProductB1) UseProductB() string {
    	return "Das Ergebnis des Produkts B1."
    }
    
    // Interaktion B1 mit beliebigem AbstractProductA
    func (*ConcreteProductB1) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Das Ergebnis der Zusammenarbeit von B1 mit (%s)", result)
    }
    
    // Konkretes Produkt B2
    type ConcreteProductB2 struct{}
    
    func (*ConcreteProductB2) UseProductB() string {
    	return "Das Ergebnis des Produkts B2."
    }
    
    // Interaktion B2 mit beliebigem AbstractProductA
    func (*ConcreteProductB2) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Das Ergebnis der Zusammenarbeit von B2 mit (%s)", result)
    }
    
    // Schnittstelle der abstrakten Fabrik
    type AbstractFactory interface {
    	CreateProductA() AbstractProductA
    	CreateProductB() AbstractProductB
    }
    
    // Konkrete Fabrik 1
    type ConcreteFactory1 struct{}
    
    func (*ConcreteFactory1) CreateProductA() AbstractProductA {
    	return &ConcreteProductA1{}
    }
    
    func (*ConcreteFactory1) CreateProductB() AbstractProductB {
    	return &ConcreteProductB1{}
    }
    
    // Konkrete Fabrik 2
    type ConcreteFactory2 struct{}
    
    func (*ConcreteFactory2) CreateProductA() AbstractProductA {
    	return &ConcreteProductA2{}
    }
    
    func (*ConcreteFactory2) CreateProductB() AbstractProductB {
    	return &ConcreteProductB2{}
    }
    
    // Client-Code, das mit der Fabrik arbeitet
    func ClientCode(factory AbstractFactory) {
    	productA := factory.CreateProductA()
    	productB := factory.CreateProductB()
    
    	fmt.Println(productB.UseProductB())
    	fmt.Println(productB.AnotherFunctionB(productA))
    }
    
    func main() {
    	fmt.Println("Kunde: Testet den Client-Code mit dem ersten Fabriktyp:")
    	ClientCode(&ConcreteFactory1{})
    
    	fmt.Println("Kunde: Testet den gleichen Client-Code mit dem zweiten Fabriktyp:")
    	ClientCode(&ConcreteFactory2{})
    }
    

Der Hauptunterschied zwischen Fabrikmethode und abstrakter Fabrik: Die Fabrikmethode erstellt einzelne Produkte, während die abstrakte Fabrik Familien von Produkten erstellt.

Mustername Beschreibung Wann verwenden
Einfache Fabrik Methode in einer Klasse zur Erstellung verschiedener Objekttypen. Für einfache Objekterstellung ohne Notwendigkeit einer Fabrikhierarchie.
Fabrikmethode Schnittstelle zur Objekterstellung, die Unterklassen entscheiden lässt, welche Klasse instanziiert wird. Wenn eine Klasse den Objekttyp, den sie erstellen soll, nicht vorhersagen kann.
Abstrakte Fabrik Schnittstelle zur Erstellung verwandter Objektfamilien. Wenn das System unabhängig von der Erzeugungs- und Repräsentationsweise seiner Produkte sein soll.

Das Fabrikmuster fördert eine schwache Kopplung des Codes und erleichtert die Hinzufügung neuer Produkttypen, ohne den Client-Code zu ändern.