GoFデザインパターン ~Template Methodパターン~
こちらを読みながら進める。
- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2004/06/19
- メディア: 大型本
- 購入: 51人 クリック: 762回
- この商品を含むブログ (397件) を見る
Template Methodパターンとは
抽象クラスで処理の枠組みを決め、実処理は具象クラスで行うというのがTemplate Methodパターン。下図でいうと、抽象クラスであるTemplateのexec()でmethodA(), methodB(), methodC()を利用するが、その具体的な実装はConcrete1, Concrete2クラスの責務となる。骨組みは抽象クラスで、肉付けは具象クラスでというイメージ。
実装
増補改訂版Java言語で学ぶデザインパターン入門で使われてる例をGoで実装してみる。
Template Methodパターンは抽象クラスを利用するが、Goには継承が存在しない(埋め込みで継承っぽいこともできるが、親構造体から子構造体のメソッドを呼べないなど厳密には継承とはいえない)ため、Javaなどの言語とは異なる実装になる。
ディレクトリ構成は以下
./3_template_method ├── main.go └── printer ├── abstract_printer.go ├── char_display.go ├── printer.go ├── string_display.go
抽象クラス
package printer type AbstractPrinter struct { } func (*AbstractPrinter) Display(printer Printer) string { result := printer.Open() result += printer.Print() result += printer.Close() return result }
テンプレートメソッドである Display()
の引数でPrinterインターフェース(を実装した子クラスのインスタンス)を受け取る。
継承は行なっていないが、こうすることで骨組みであるAbstractPrinterクラスのテンプレートメソッド(Display()
)で具象クラスのメソッドを呼ぶことができる。
具象クラス
具象クラスのインターフェース。継承のある言語では継承の機能を使って子クラスの実装を担保できるが、Goではインターフェースによって具象クラスの実装を担保する。
具象クラスに要求されるのは open()
print()
close()
の実装。
package printer type Printer interface { Open() string Print() string Close() string }
AbstractPrinterの具象クラスであるCharDisplay, StringDisplay
package printer type charDisplay struct { char string } func NewCharDisplay(char string) Printer { return &charDisplay{char: char} } func (*charDisplay) Open() string { return "<<" } func (cd *charDisplay) Print() string { return cd.char } func (*charDisplay) Close() string { return ">>" }
package printer type stringDisplay struct { char string } func NewStringDisplay(char string) Printer { return &stringDisplay{char: char} } func (*stringDisplay) Open() string { return "+--+" } func (cd *stringDisplay) Print() string { return "|" + cd.char + "|" } func (*stringDisplay) Close() string { return "+--+" }
Main
Main実装
package main import ( "fmt" "github.com/saekis/go-design-pattern/3_template_method/printer" ) func main() { ad := printer.AbstractPrinter{} fmt.Println(ad.Display(printer.NewCharDisplay("char_display"))) fmt.Println(ad.Display(printer.NewStringDisplay("string_display"))) }
実行結果
$ go run main.go <<char_display>> +--+|string_display|+--+
クラス図