Golangで、デザインパターン「Factory Method」を学ぶ

GoFのデザインパターンを学習する素材として、書籍「[増補改訂版Java言語で学ぶデザインパターン入門](https://www.hyuki.com/dp/)」が参考になるみたいですね。
取り上げられている実例は、JAVAベースのため、Pythonで同等のプラクティスに挑んだことがありました。
[Qiita記事: "Pythonで、デザインパターン「Factory Method」を学ぶ"](https://qiita.com/ttsubo/items/623f32f9e96cb16d04a4)

今回は、Pythonで実装した” Factory Method”のサンプルアプリをGolangで実装し直してみました。

# ■ Factory Method（ファクトリメソッド）
Factory Method パターン（ファクトリメソッド・パターン）とは、GoF (Gang of Four; 四人組)によって定義されたデザインパターンの1つである。 Factory Method パターンは、他のクラスのコンストラクタをサブクラスで上書き可能な自分のメソッドに置き換えることで、 アプリケーションに特化したオブジェクトの生成をサブクラスに追い出し、クラスの再利用性を高めることを目的とする。
Virtual Constructor パターンとも呼ばれる。
## UML class diagram
![W3sDesign_Factory_Method_Design_Pattern_UML.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103595/5aafd9df-5a63-e2c0-07bd-c96a1f4adc8f.jpeg)
![1000px-Factory_Method_UML_class_diagram.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103595/b9848fca-7aef-a749-fb9e-fb0e219ec7db.png)
[(以上、ウィキペディア（Wikipedia）より引用)](https://ja.wikipedia.org/wiki/Factory_Method_パターン)
## □ 備忘録
[振る舞いに関する`Template Method`パターン](https://ja.wikipedia.org/wiki/Template_Method_パターン)は、スーパークラスで処理の大枠を作って、サブクラスで具体的処理を決定するというもの。この`Template Method`パターンを、インスタンスをつくる場面に適用したものが、`Factory Method`パターンらしい。

# ■ "Factory Method"のサンプルプログラム
Factory Methodパターンは、以下の特徴があるようです。

- インスタンスの作り方をスーパークラス側で定める
- 具体的なクラス名までは定めない
- 具体的な肉付けは、全てサブクラス側で行う

これによって、インスタンス作成のための枠組み（フレームワーク）と実際のインスタンス作成のクラスを分けて考えることができるようになるそうです。
実際に、Factory Methodパターンを使って、「身分証明書カード（IDカード）を作る工場」を題材としたサンプルプログラムを動かしてみて、次のような動作の様子を確認したいと思います。

- `Hiroshi Yuki"`, `Tomura`, `Hanako Sato`の３名の身分証明書カードを作成する
- `Hiroshi Yuki"`, `Tomura`, `Hanako Sato`の３名の身分証明書カードを使用する

```
$ go run Main.go 
I'll create Hiroshi Yuki's card
I'll create Tomura's card
I'll create Hanako Sato's card
I'll use Hiroshi Yuki's card
I'll use Tomura's card
I'll use Hanako Sato's card
```
サンプルプログラムを動かしただけだと、いまいち、何がしたいのかよく分かりませんね
つづいて、サンプルプログラムの詳細を確認していきます。

# ■ サンプルプログラムの詳細
Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern_with_golang/tree/master/FactoryMethod

- ディレクトリ構成

```console
.
├── Main.go
└── framework
    ├── factory.go
    └── id_card_factory.go
```

## (1) Product（製品）の役
`Product`役では、インスタンスが持つべきインタフェースを定めます。
サンプルプログラムでは、`Product`インタフェースが、この役を努めます。

```go:framework/factory.go
package factoryMethod

... (snip)

// Product is interface
type Product interface {
	Use()
	getOwner() string
}
```
## (2) Creator（作成者）の役
`Creator`役では、`Product`を生成する役割を担います。実際に生成する`ConcreteProduct`役については何も知りません。
さらに、`Creator`役には、インスタンスの各部分を作るためのメソッドが用意されます。
サンプルプログラムでは、`Factory`構造体が、この役を努めます。

```go:framework/factory.go
package factoryMethod

// FactoryInterface is interface
type FactoryInterface interface {
	createProduct(owner string) Product
	registerProduct(Product)
	Create(owner string) Product
}

// Factory is struct
type Factory struct {
	factory FactoryInterface
}

// Create func for creating product
func (f *Factory) Create(owner string) Product {
	p := f.factory.createProduct(owner)
	f.factory.registerProduct(p)
	return p
}

... (snip)
```
## (3) ConcreteProduct（具体的製品）の役
`ConcreteProduct`役は、`Product`役のインタフェースを実装しているクラスです。実際のインスタンス作成後に呼び出されるメソッドが、ここで定義されます。
サンプルプログラムでは、`iDCardProduct`構造体が、この役を努めます。

```go:framework/id_card_factory.go
package factoryMethod

... (snip)

type iDCardProduct struct {
	owner string
}

func newIDCardProduct(owner string) *iDCardProduct {
	fmt.Printf("I'll create %s's card\n", owner)
	return &iDCardProduct{owner}
}

// Use func for using card
func (i *iDCardProduct) Use() {
	fmt.Printf("I'll use %s's card\n", i.owner)
}

func (i *iDCardProduct) getOwner() string {
	return i.owner
}
```
## (4) ConcreteCreator（具体的作成者）の役
`ConcreteCreator`役は、`Creator`役のインタフェースを実装しているクラスです。具体的な製品を作るクラスを定めます。
サンプルプログラムでは、`IDCardFactory`構造体が、この役を努めます。

```go:framework/id_card_factory.go
package factoryMethod

import "fmt"

// IDCardFactory is struct
type IDCardFactory struct {
	*Factory
	owners []string
}

// NewIDCardFactory func for initializing IDCardFactory
func NewIDCardFactory() *IDCardFactory {
	idCardFactory := &IDCardFactory{
		Factory: &Factory{},
	}
	idCardFactory.factory = idCardFactory
	return idCardFactory
}

func (i *IDCardFactory) createProduct(owner string) Product {
	return newIDCardProduct(owner)
}

func (i *IDCardFactory) registerProduct(product Product) {
	i.owners = append(i.owners, product.getOwner())
}

... (snip)
```

## (5) Client（依頼人）の役
サンプルプログラムでは、`startMain`関数が、この役を努めます。

```go:Main.go
package main

import (
	factoryMethod "./framework"
)

func startMain(factoryObject factoryMethod.FactoryInterface) {
	card1 := factoryObject.Create("Hiroshi Yuki")
	card2 := factoryObject.Create("Tomura")
	card3 := factoryObject.Create("Hanako Sato")
	card1.Use()
	card2.Use()
	card3.Use()
}

func main() {
	startMain(factoryMethod.NewIDCardFactory())
}
```

# ■ 参考URL
- [Pythonで、デザインパターン「Factory Method」を学ぶ](https://qiita.com/ttsubo/items/623f32f9e96cb16d04a4)