Hura! Mamy wreszcie przyjemność udostępnić wam polską wersję! Zapraszamy do przesyłania wiadomości z waszymi uwagami i informacjami o zauważonych błędach.
Metoda wytwórcza

Metoda wytwórcza w języku Go

Metoda wytwórcza jest kreacyjnym wzorcem projektowym rozwiązującym problem tworzenia obiektów-produktów bez określania ich konkretnych klas.

Metoda wytwórcza definiuje metodę która ma służyć tworzeniu obiektów bez bezpośredniego wywoływania konstruktora (poprzez operator new). Podklasy mogą nadpisać tę metodę w celu zmiany klasy tworzonych obiektów.

Jeśli masz problem ze zrozumieniem różnicy pomiędzy poszczególnymi koncepcjami i wzorcami wytwórczymi, przeczytaj nasze Porównanie fabryk.

Przykład koncepcyjny

W Go nie da się zaimplementować klasycznego wzorca Metody wytwórczej z racji braku takich funkcjonalności języków obiektowych jak klasy i dziedziczenie. Możemy jednak zaimplementować jego okrojoną wersję - Fabrykę Prostą.

W poniższym przykładzie będziemy produkować różne rodzaje broni stosując strukturę fabryczną.

Zaczniemy od stworzenia interfejsu iGun definiującego wszystkie metody właściwe broniom. Mamy typ struktury gun implementujący interfejs iGun. Dwie konkretne bronie — ak47 i muszkiet zawierają strukturę broni i pośrednio implementują wszystkie metody iGun.

Struktura gunFactory służy za fabrykę tworzącą bronie wybranego typu na podstawie przekazanego jej argumentu. Klientem jest tu main.go. Zamiast pracować bezpośrednio z ak47 lub z muszkietem, zależna jest od gunFactory w zakresie generowania instancji różnych typów broni zależnie od parametrów-łańcuchów znaków.

iGun.go: Interfejs produktu

package main

type iGun interface {
	setName(name string)
	setPower(power int)
	getName() string
	getPower() int
}

gun.go: Konkretny produkt

package main

type gun struct {
	name  string
	power int
}

func (g *gun) setName(name string) {
	g.name = name
}

func (g *gun) getName() string {
	return g.name
}

func (g *gun) setPower(power int) {
	g.power = power
}

func (g *gun) getPower() int {
	return g.power
}

ak47.go: Konkretny produkt

package main

type ak47 struct {
	gun
}

func newAk47() iGun {
	return &ak47{
		gun: gun{
			name:  "AK47 gun",
			power: 4,
		},
	}
}

musket.go: Konkretny produkt

package main

type musket struct {
	gun
}

func newMusket() iGun {
	return &musket{
		gun: gun{
			name:  "Musket gun",
			power: 1,
		},
	}
}

gunFactory.go: Fabryka

package main

import "fmt"

func getGun(gunType string) (iGun, error) {
	if gunType == "ak47" {
		return newAk47(), nil
	}
	if gunType == "musket" {
		return newMusket(), nil
	}
	return nil, fmt.Errorf("Wrong gun type passed")
}

main.go: Kod klienta

package main

import "fmt"

func main() {
	ak47, _ := getGun("ak47")
	musket, _ := getGun("musket")

	printDetails(ak47)
	printDetails(musket)
}

func printDetails(g iGun) {
	fmt.Printf("Gun: %s", g.getName())
	fmt.Println()
	fmt.Printf("Power: %d", g.getPower())
	fmt.Println()
}

output.txt: Wynik działania

Gun: AK47 gun
Power: 4
Gun: Musket gun
Power: 1
Na podstawie: Golang By Example

Metoda wytwórcza w innych językach

Wzorce projektowe: Metoda wytwórcza w języku Java Wzorce projektowe: Metoda wytwórcza w języku C# Wzorce projektowe: Metoda wytwórcza w języku C++ Wzorce projektowe: Metoda wytwórcza w języku PHP Wzorce projektowe: Metoda wytwórcza w języku Python Wzorce projektowe: Metoda wytwórcza w języku Ruby Wzorce projektowe: Metoda wytwórcza w języku Swift Wzorce projektowe: Metoda wytwórcza w języku TypeScript