Sobes.tech
Middle

Vertel me over het Factory-patroon.

sobes.tech AI

Antwoord van AI

Fabriek is een creational pattern dat een gemeenschappelijke interface biedt voor het maken van objecten in de superklasse, terwijl subklassen het type van de gemaakte objecten kunnen wijzigen.

  • Eenvoudige Fabriek (Simple Factory): Is geen puur patroon, eerder een idiom. Een klasse met een methode die objecten maakt op basis van invoerparameters.

    package main
    
    import "fmt"
    
    type Product interface {
    	Use()
    }
    
    type ConcreteProductA struct{}
    
    func (p *ConcreteProductA) Use() {
    	fmt.Println("Gebruik van Concrete Product A")
    }
    
    type ConcreteProductB struct{}
    
    func (p *ConcreteProductB) Use() {
    	fmt.Println("Gebruik van 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()
    }
    
  • Factory Method (Factory Method): Definieert een interface voor het maken van een object, maar laat subklassen beslissen welke klasse te instantieren.

    package main
    
    import "fmt"
    
    // Product interface
    type Product interface {
    	Operation() string
    }
    
    // Concrete product A
    type ConcreteProduct1 struct{}
    
    func (p *ConcreteProduct1) Operation() string {
    	return "Resultaat van ConcreteProduct1"
    }
    
    // Concrete product B
    type ConcreteProduct2 struct{}
    
    func (p *ConcreteProduct2) Operation() string {
    	return "Resultaat van ConcreteProduct2"
    }
    
    // Creator interface
    type Creator interface {
    	FactoryMethod() Product
    	SomeOperation() string
    }
    
    // Basisklasse van de maker
    type BaseCreator struct{}
    
    func (bc *BaseCreator) SomeOperation() string {
    	// Roep de fabrieksmethode aan om het productobject te krijgen
    	product := bc.FactoryMethod()
    	// Gebruik het product
    	result := "Creator: Dezelfde code van de maker heeft net gewerkt met " + product.Operation()
    	return result
    }
    
    // Concrete maker A
    type ConcreteCreator1 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator1) FactoryMethod() Product {
    	return &ConcreteProduct1{} // Maakt ConcreteProductA
    }
    
    // Concrete maker B
    type ConcreteCreator2 struct {
    	BaseCreator
    }
    
    func (cc *ConcreteCreator2) FactoryMethod() Product {
    	return &ConcreteProduct2{} // Maakt ConcreteProductB
    }
    
    func main() {
    	// Voorbeeld van gebruik
    	creator1 := &ConcreteCreator1{}
    	fmt.Println(creator1.SomeOperation())
    
    	creator2 := &ConcreteCreator2{}
    	fmt.Println(creator2.SomeOperation())
    }
    
  • Abstracte Fabriek (Abstract Factory): Biedt een interface voor het maken van families van gerelateerde of afhankelijke objecten zonder hun concrete klassen te specificeren.

    package main
    
    import "fmt"
    
    // Interface voor product A
    type AbstractProductA interface {
    	UseProductA() string
    }
    
    // Concrete product A1
    type ConcreteProductA1 struct{}
    
    func (*ConcreteProductA1) UseProductA() string {
    	return "Het resultaat van product A1."
    }
    
    // Concrete product A2
    type ConcreteProductA2 struct{}
    
    func (*ConcreteProductA2) UseProductA() string {
    	return "Het resultaat van product A2."
    }
    
    // Interface voor product B
    type AbstractProductB interface {
    	UseProductB() string
    	AnotherFunctionB(collaborator AbstractProductA) string // Samenwerking met product A
    }
    
    // Concrete product B1
    type ConcreteProductB1 struct{}
    
    func (*ConcreteProductB1) UseProductB() string {
    	return "Het resultaat van product B1."
    }
    
    // Samenwerking B1 met elk type AbstractProductA
    func (*ConcreteProductB1) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Het resultaat van B1 die samenwerkt met (%s)", result)
    }
    
    // Concrete product B2
    type ConcreteProductB2 struct{}
    
    func (*ConcreteProductB2) UseProductB() string {
    	return "Het resultaat van product B2."
    }
    
    // Samenwerking B2 met elk type AbstractProductA
    func (*ConcreteProductB2) AnotherFunctionB(collaborator AbstractProductA) string {
    	result := collaborator.UseProductA()
    	return fmt.Sprintf("Het resultaat van B2 die samenwerkt met (%s)", result)
    }
    
    // Interface voor abstracte fabriek
    type AbstractFactory interface {
    	CreateProductA() AbstractProductA
    	CreateProductB() AbstractProductB
    }
    
    // Concrete fabriek 1
    type ConcreteFactory1 struct{}
    
    func (*ConcreteFactory1) CreateProductA() AbstractProductA {
    	return &ConcreteProductA1{}
    }
    
    func (*ConcreteFactory1) CreateProductB() AbstractProductB {
    	return &ConcreteProductB1{}
    }
    
    // Concrete fabriek 2
    type ConcreteFactory2 struct{}
    
    func (*ConcreteFactory2) CreateProductA() AbstractProductA {
    	return &ConcreteProductA2{}
    }
    
    func (*ConcreteFactory2) CreateProductB() AbstractProductB {
    	return &ConcreteProductB2{}
    }
    
    // Klantcode die met de fabriek werkt
    func ClientCode(factory AbstractFactory) {
    	productA := factory.CreateProductA()
    	productB := factory.CreateProductB()
    
    	fmt.Println(productB.UseProductB())
    	fmt.Println(productB.AnotherFunctionB(productA))
    }
    
    func main() {
    	fmt.Println("Klant: Testen van klantcode met de eerste fabriektype:")
    	ClientCode(&ConcreteFactory1{})
    
    	fmt.Println("Klant: Testen van dezelfde klantcode met het tweede fabriektype:")
    	ClientCode(&ConcreteFactory2{})
    }
    

Het belangrijkste verschil tussen Factory Method en Abstract Factory: Factory Method creëert enkele producten, terwijl Abstract Factory families van producten creëert.

Pattern naam Beschrijving Wanneer te gebruiken
Eenvoudige Fabriek Methode in één klasse voor het maken van verschillende typen objecten. Voor eenvoudige objectcreatie zonder behoefte aan een fabriekhiërarchie.
Factory Method Interface voor het maken van een object, waarbij subklassen beslissen welke klasse te instantiëren. Wanneer een klasse het type object dat het moet maken niet kan voorspellen.
Abstracte Fabriek Interface voor het maken van families van gerelateerde objecten. Wanneer het systeem onafhankelijk moet zijn van de manier waarop de producten worden gemaakt en gepresenteerd.

Het Fabriek patroon bevordert losgekoppelde code en maakt het toevoegen van nieuwe producttypen zonder de clientcode te wijzigen gemakkelijker.