saeki’s blog

The limits of my code mean the limits of my world.

GoFデザインパターン ~Factory Methodパターン~

こちらを読みながら進める。

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

Factory Methodパターンとは

Template Methodパターンではスーパークラスで処理の枠組みを決め具体的な処理は子クラスで実装したが、それをインスタンス生成に適用したのがFactory Methodパターン。Factory Methodパターンによって、インスタンス生成の枠組みとインスタンス生成の実装を分けることができる。

f:id:t_saeki:20190712190500p:plain

実装

増補改訂版Java言語で学ぶデザインパターン入門で使われてる例をGoで実装してみる。

ディレクトリ構成は以下

./4_factory_method
├── framework
│   ├── creater.go
│   ├── factory.go
│   └── product.go
├── idcard
│   ├── idcard.go
│   └── idcard_factory.go
└── main.go

frameworkパッケージ

package framework

type Creater interface {
    CreateProduct(string) Product
    RegisterProduct(Product)
}

type Product interface {
    Use() string
    GetOwner() string
}

type Factory struct {}

func (*Factory) Create(creater Creater, owner string) Product {
    p := creater.CreateProduct(owner)
    creater.RegisterProduct(p)
    return p
}

Goで実装しようとするとImplementFactoryにFactoryを継承させることは難しいため、Factory.Create() にCreaterインターフェースを実装したImplementFactoryを渡すことでポリモーフィズムを実現するようにした

idcardパッケージ

このパッケージがインスタンス生成の具体的な処理を担う

package idcard

import (
    "fmt"

    "github.com/saekis/go-design-pattern/4_factory_method/framework"
)

type IdCard struct {
    owner string
}

func NewIdCard(owner string) framework.Product {
    return &IdCard{owner: owner}
}

func (ic *IdCard) Use() string {
    return fmt.Sprintf("Use %s's card", ic.owner)
}

func (ic *IdCard) GetOwner() string {
    return ic.owner
}

type IdCardFactory struct {
    owners []string
}

func NewIdCardFactory() framework.Creater {
    return &IdCardFactory{owners: []string{}}
}

func (*IdCardFactory) CreateProduct(owner string) framework.Product {
    return NewIdCard(owner)
}

func (factory *IdCardFactory) RegisterProduct(p framework.Product) {
    factory.owners = append(factory.owners, p.GetOwner())
}

IdCardFactory構造体がFactory Methodパターンにおけるインスタンス生成の具体的な処理を実装するクラス

Main

Main実装

package main

import (
    "fmt"

    "github.com/saekis/go-design-pattern/4_factory_method/framework"

    "github.com/saekis/go-design-pattern/4_factory_method/idcard"
)

func main() {
    factory := framework.Factory{}
    creater := idcard.NewIdCardFactory()
    card1 := factory.Create(creater, "たろう")
    card2 := factory.Create(creater, "はなこ")
    card3 := factory.Create(creater, "たかし")

    fmt.Println(card1.Use())
    fmt.Println(card2.Use())
    fmt.Println(card3.Use())
}

実行結果

$ go run main.go 
Use たろう's card
Use はなこ's card
Use たかし's card

実装したもの

github.com