Menu
Coddy logo textTech

Abstract-Factory-Muster

Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 88 von 107.

Das Abstract Factory-Muster erweitert das Factory-Muster, indem es Familien verwandter Objekte erstellt, ohne deren konkrete Typen anzugeben. Anstelle einer einzelnen Factory-Funktion definieren Sie ein Factory-Interface, das mehrere konkrete Factories implementieren, wobei jede ein konsistentes Set verwandter Objekte erzeugt.

Stellen Sie sich ein UI-Toolkit vor, das Schaltflächen und Kontrollkästchen erstellen muss. Verschiedene Betriebssysteme erfordern unterschiedliche Implementierungen, aber die Komponenten müssen konsistent zusammenarbeiten:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

// Abstraktes Factory-Interface
type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

Jede konkrete Fabrik produziert eine Familie verwandter Komponenten:

// Windows-Familie
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// Mac-Familie
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

Der Client-Code arbeitet mit dem Factory-Interface und bleibt dabei unabhängig von konkreten Implementierungen:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

Verwenden Sie die Abstract Factory, wenn Ihr System mit mehreren Familien verwandter Produkte arbeiten muss und Sie sicherstellen möchten, dass Komponenten aus derselben Familie zusammen verwendet werden. Sie ist komplexer als eine einfache Factory, greifen Sie also nur darauf zurück, wenn Sie tatsächlich Produktfamilien verwalten müssen.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Möbelhaussystem mit dem Abstract Factory Pattern erstellen! Sie werden Fabriken erstellen, die Familien verwandter Möbelstücke produzieren – jede Fabrik produziert einen konsistenten Stil (Modern oder Vintage) und stellt so sicher, dass Stühle und Tische aus derselben Fabrik ästhetisch zusammenpassen.

Sie werden Ihren Code auf drei Dateien verteilen:

  • furniture.go: Definieren Sie Ihre Produkt-Interfaces und konkreten Möbeltypen.

    Erstellen Sie zwei Produkt-Interfaces:

    • Chair mit einer Methode SitOn() string
    • Table mit einer Methode PlaceItems() string

    Implementieren Sie zwei Möbelfamilien:

    • Modern-Familie: ModernChair gibt Sitting on a sleek modern chair zurück und ModernTable gibt Placing items on a glass modern table zurück
    • Vintage-Familie: VintageChair gibt Sitting on an ornate vintage chair zurück und VintageTable gibt Placing items on a wooden vintage table zurück
  • factory.go: Definieren Sie Ihr Abstract Factory Interface und die konkreten Fabriken.

    Erstellen Sie ein FurnitureFactory Interface mit zwei Methoden:

    • CreateChair() Chair
    • CreateTable() Table

    Implementieren Sie zwei konkrete Fabriken:

    • ModernFactory, die ModernChair und ModernTable produziert
    • VintageFactory, die VintageChair und VintageTable produziert

    Erstellen Sie außerdem eine Funktion GetFactory(style string) FurnitureFactory, die basierend auf dem Stil (modern oder vintage) die entsprechende Fabrik zurückgibt. Verwenden Sie standardmäßig ModernFactory für nicht erkannte Stile.

  • main.go: Verwenden Sie Ihre Fabriken, um Räume einzurichten.

    Erstellen Sie eine Funktion FurnishRoom(factory FurnitureFactory) string, die die Fabrik verwendet, um einen Stuhl und einen Tisch zu erstellen, und dann einen formatierten String zurückgibt, der beide Aktionen in separaten Zeilen anzeigt.

    Lesen Sie eine Stileingabe ein, rufen Sie die entsprechende Fabrik ab, richten Sie einen Raum ein und geben Sie das Ergebnis aus.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Möbelstil (modern, vintage oder etwas anderes)

Zum Beispiel, bei der Eingabe:

modern

Sollte Ihre Ausgabe wie folgt aussehen:

Sitting on a sleek modern chair
Placing items on a glass modern table

Und bei der Eingabe:

vintage

Sollte Ihre Ausgabe wie folgt aussehen:

Sitting on an ornate vintage chair
Placing items on a wooden vintage table

Und bei der Eingabe:

rustic

Sollte Ihre Ausgabe wie folgt aussehen:

Sitting on a sleek modern chair
Placing items on a glass modern table

Beachten Sie, wie die Funktion FurnishRoom über das Interface mit jeder Fabrik zusammenarbeitet – sie weiß nicht, ob sie moderne oder Vintage-Möbel erstellt. Dies stellt sicher, dass alle Möbel in einem Raum aus derselben Familie stammen und ein konsistenter Stil beibehalten wird!

Spickzettel

Das Abstract Factory Pattern (Abstrakte Fabrik) erstellt Familien verwandter Objekte, ohne deren konkrete Typen anzugeben. Es definiert eine Factory-Schnittstelle, die von mehreren konkreten Factories implementiert wird, wobei jede einen konsistenten Satz verwandter Objekte erzeugt.

Struktur

Definieren Sie Produkt-Schnittstellen für jeden Objekttyp:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

Erstellen Sie ein Interface für eine abstrakte Fabrik, das Methoden zur Erstellung der einzelnen Produkttypen deklariert:

type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

Konkrete Implementierungen

Implementieren Sie konkrete Produktfamilien, bei denen jede Familie ein konsistentes Styling oder Verhalten aufweist:

// Windows-Familie
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// Mac-Familie
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

Client-Code

Der Client-Code arbeitet mit dem Factory-Interface und bleibt unabhängig von konkreten Implementierungen:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

Wann man es verwendet

Verwenden Sie die Abstrakte Fabrik, wenn Ihr System mit mehreren Familien verwandter Produkte arbeiten muss und Sie sicherstellen möchten, dass Komponenten aus derselben Familie zusammen verwendet werden. Es ist komplexer als eine einfache Factory, verwenden Sie es also nur, wenn Sie tatsächlich Produktfamilien verwalten müssen.

Probier es selbst

package main

import "fmt"

// FurnishRoom verwendet eine Factory, um Möbel zu erstellen, und gibt das Ergebnis zurück
// TODO: Implementiere diese Funktion
// - Verwende die Factory, um einen Stuhl und einen Tisch zu erstellen
// - Gib einen String zurück, der das Ergebnis von SitOn() in der ersten Zeile und das Ergebnis von PlaceItems() in der zweiten Zeile enthält
func FurnishRoom(factory FurnitureFactory) string {
	// TODO: Erstelle Stuhl und Tisch mithilfe der Factory
	// TODO: Gib einen formatierten String mit beiden Aktionen in separaten Zeilen zurück
	return ""
}

func main() {
	var style string
	fmt.Scanln(&style)

	// TODO: Hole die passende Factory basierend auf dem Stil
	// TODO: Richte einen Raum mithilfe der Factory ein
	// TODO: Gib das Ergebnis aus
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung