俺の新 Git コース見てよ! おーい!俺の新 Git コース見てよ! おーい!GitByBit.com に俺の新 Git コースあるよ、見てみ! おーい!Git をサクッと復習したい?GitByBit.com の俺の新コース見てみ!
Factory Method

Factory Method を Go で

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

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

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

概念的な例

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

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

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

gun­Factory 構造体はファクトリーとして機能し、 入力引数に応じて望みの種類の銃を作成します。 main.go< は、 クライアントです。 直接 ak47 や musket と関わる代わりに、 種々の銃のインスタンスの作成を 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 で