春のセール
Factory Method

Factory Method を Go で

Factory Method 生成に関するデザインパターンの一つで 具象クラスを指定することなく プロダクト 訳注 本パターンでは 生成されるモノのことを一般にプロダクトと呼びます のオブジェクトを生成することを可能とします

Factory Method では オブジェクトの生成において 直接のコンストラクター呼び出し new 演算子 代わりに使用すべきメソッドを定義します サブクラスにおいてこのメソッドを上書きすることにより 生成されるオブジェクトのクラスを変更します

もし各種ファクトリー系のパターンやコンセプトの違いで迷った場合は ファクトリーの比較 をご覧ください

概念的な例

Go には クラスや継承などの OOP 機能がないため Go で古典的な Factory Method パターンを実装することは不可能です ただし パターンの簡易版である単純ファクトリーなら実装できます

この例では ファクトリー構造体を使用して 多種の兵器を製造します

最初に i­Gun インターフェースを作成します これは 銃が持つべき全メソッドを定義します gun 構造体は iGun インターフェースを実装します 二つの具象銃 ak47musket 両方とも gun 構造体を埋め込み 間接的に i­Gun の全メソッドを実装します

gun­Factory 構造体はファクトリーとして機能し 入力引数に応じて望みの種類の銃を作成します main.go< クライアントです 直接 ak47musket と関わる代わりに 種々の銃のインスタンスの作成を gun­Factory に頼ります 文字列パラメーターが製造を管理します

iGun.go: プロダクト・インターフェース

package main

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

gun.go: 具象プロダクト

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: 具象プロダクト

package main

type Ak47 struct {
	Gun
}

func newAk47() IGun {
	return &Ak47{
		Gun: Gun{
			name:  "AK47 gun",
			power: 4,
		},
	}
}

musket.go: 具象プロダクト

package main

type musket struct {
	Gun
}

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

gunFactory.go: ファクトリー

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: クライアント・コード

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: 実行結果

Gun: AK47 gun
Power: 4
Gun: Musket gun
Power: 1

他言語での Factory Method

Factory Method を C# で Factory Method を C++ で Factory Method を Java で Factory Method を PHP で Factory Method を Python で Factory Method を Ruby で Factory Method を Rust で Factory Method を Swift で Factory Method を TypeScript で