Menu
Coddy logo textTech

Wzorzec Abstract Factory

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 88 z 107.

Wzorzec Fabryki Abstrakcyjnej rozszerza wzorzec Fabryki, tworząc rodziny powiązanych obiektów bez określania ich konkretnych typów. Zamiast pojedynczej funkcji fabrykującej definiujesz interfejs fabryki, który implementuje wiele konkretnych fabryk, z których każda tworzy spójny zestaw powiązanych obiektów.

Wyobraź sobie zestaw narzędzi UI, który musi tworzyć przyciski i pola wyboru. Różne systemy operacyjne wymagają różnych implementacji, ale komponenty muszą ze sobą spójnie współpracować:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

// Interfejs fabryki abstrakcyjnej
type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

Każda konkretna fabryka wytwarza rodzinę powiązanych komponentów:

// Rodzina Windows
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{} }

// Rodzina Mac
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{} }

Kod klienta korzysta z interfejsu fabryki, pozostając niezależny od konkretnych implementacji:

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

Używaj wzorca Abstract Factory, gdy Twój system musi obsługiwać wiele rodzin powiązanych produktów i chcesz mieć pewność, że komponenty z tej samej rodziny będą używane razem. Jest bardziej złożony niż prosty wzorzec Factory, więc sięgaj po niego tylko wtedy, gdy naprawdę potrzebujesz zarządzać rodzinami produktów.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system sklepu meblowego, używając wzorca Abstract Factory! Utworzysz fabryki, które produkują rodziny powiązanych ze sobą mebli: każda fabryka produkuje meble w spójnym stylu (Modern lub Vintage), dzięki czemu krzesła i stoły z tej samej fabryki pasują do siebie pod względem estetycznym.

Uporządkujesz swój kod w trzech plikach:

  • furniture.go: Zdefiniuj interfejsy produktów i konkretne typy mebli.

    Utwórz dwa interfejsy produktów:

    • Chair z metodą SitOn() string
    • Table z metodą PlaceItems() string

    Zaimplementuj dwie rodziny mebli:

    • Rodzina Modern: ModernChair zwraca Sitting on a sleek modern chair, a ModernTable zwraca Placing items on a glass modern table
    • Rodzina Vintage: VintageChair zwraca Sitting on an ornate vintage chair, a VintageTable zwraca Placing items on a wooden vintage table
  • factory.go: Zdefiniuj interfejs abstrakcyjnej fabryki oraz konkretne fabryki.

    Utwórz interfejs FurnitureFactory z dwiema metodami:

    • CreateChair() Chair
    • CreateTable() Table

    Zaimplementuj dwie konkretne fabryki:

    • ModernFactory, która produkuje ModernChair i ModernTable
    • VintageFactory, która produkuje VintageChair i VintageTable

    Utwórz również funkcję GetFactory(style string) FurnitureFactory, która zwraca odpowiednią fabrykę na podstawie stylu (modern lub vintage). W przypadku nierozpoznanych stylów domyślnie zwracaj ModernFactory.

  • main.go: Użyj fabryk, aby umeblować pokoje.

    Utwórz funkcję FurnishRoom(factory FurnitureFactory) string, która używa fabryki do utworzenia krzesła i stołu, a następnie zwraca sformatowany ciąg znaków przedstawiający obie czynności w osobnych wierszach.

    Wczytaj styl, pobierz odpowiednią fabrykę, umebluj pokój i wypisz wynik.

Podane zostaną następujące dane wejściowe:

  • Wiersz 1: Styl mebli (modern, vintage lub dowolny inny)

Na przykład dla danych wejściowych:

modern

Wynik powinien być następujący:

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

A dla danych wejściowych:

vintage

Wynik powinien być następujący:

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

A dla danych wejściowych:

rustic

Wynik powinien być następujący:

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

Zwróć uwagę, że funkcja FurnishRoom współpracuje z dowolną fabryką za pośrednictwem interfejsu. Nie wie, czy tworzy meble w stylu Modern, czy Vintage. Dzięki temu wszystkie meble w pokoju pochodzą z tej samej rodziny i zachowują spójny styl!

Spróbuj swoich sił

package main

import "fmt"

// FurnishRoom używa fabryki do tworzenia mebli i zwraca wynik
// TODO: Zaimplementuj tę funkcję
// - Użyj fabryki do utworzenia krzesła i stołu
// - Zwróć ciąg znaków z wynikiem SitOn() w pierwszym wierszu i wynikiem PlaceItems() w drugim wierszu
func FurnishRoom(factory FurnitureFactory) string {
	// TODO: Utwórz krzesło i stół za pomocą fabryki
	// TODO: Zwróć sformatowany ciąg znaków z obiema czynnościami w osobnych wierszach
	return ""
}

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

	// TODO: Pobierz odpowiednią fabrykę na podstawie style
	// TODO: Umebluj pokój za pomocą fabryki
	// TODO: Wypisz wynik
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online