お久しぶりです。白々です。
先日エンジニアの先輩にデザインパターンをご存知でない!?という冷静なツッコミを頂き、その後結城浩さんが書かれた「Java言語で学ぶデザインパターン入門」を渡されたので勉強することにしました。
ただ、本を一読しても覚えられないので覚書として記事にしようと思いました。
完走できるように頑張ります。
また、「Java言語で学ぶデザインパターン入門」には、サンプルプログラムも有りますが、著作権の都合上省かせて頂きます。御了承ください。
前回は、「Adapterパターン」に関しての記事を作成しました。
前回の記事は、以下です。
https://qiita.com/sirajirasajiki/items/0d58a3b9fe9bdb460d0d
今回は、「Template Methodパターン」に関して記載したいと思います。
また、「Java言語で学ぶデザインパターン入門」には、サンプルプログラムも有りますが、著作権の都合上省かせて頂きます。御了承ください。
#第3章 Template Method -具体的な処理をサブクラスに任せる
皆さんは、ライトノベルの転生ものというジャンルをご存知でしょうか?
転生ものというジャンルは、基本的に、主人公が死ぬ→神様にあいチートをもらう→別の世界に転生する→別の世界で大活躍といった決まり切った流れがあります。
このような、雛形になるような物をテンプレート言ったりします。
ただ、テンプレートを使っても、主人公が死ぬ理由、神様からもらうチート、転生先の世界観や転生での活躍内容などは、小説によって異なりますよね。
基本的な考え方や物語の流れは変わらないけど、各場面でどのようなことをするのかは、実際に作る人が決めています。
このように、処理の枠組みを決めたクラスを継承した、サブクラスを作り、サブクラス内で実際の処理を決めるようなメソッドを「Template Methodパターン」というようです。
##なんでこんなパターンが必要なの?
同じアルゴリズムで処理をする別のクラスを、「Template Methodパターン」を使用せずに、コピー&ペーストでたくさん作った場合、同じ処理をしているアルゴリズム内でバグが見つかった場合、コピー&ペーストで作成したクラス全てに修正をかける必要があります。
「Template Methodパターン」を使用すると、スーパークラスのみ修正するだけで、継承しているクラスは全て修正することができます。
具体例として「Java言語で学ぶデザインパターン入門」にもありました、
「文字や文字列を5回繰り返して表示する」
という内容を使って考えたいと思います。
ただし、文字や文字列を表示前後には、ヘッダーとフッダーをつけるようにします。
ヘッダーをつけるメソッドを「open」とし、フッダーをつけるメソッドを「close」とし、文字や文字列を表示するメソッドを「print_string」とし、文字や文字列を5回繰り返して表示するメソッドを「display」とします。
スーパークラスでは、「open」、「close」、「print_string」の3つのメソッドは抽象メソッドで、「display」だけが実装されているものとします。
スーパークラスで実装されている「display」メソッドでは、「open」、「close」、「print_string」の3つのメソッドが使われているものとします。
ある時、「文字や文字列を5回繰り返して表示する」部分を「文字や文字列を3回繰り返して表示する」ように変更するケースを考えるとします。
スーパークラスを継承せずに、スーパークラスの処理部分をコピー&ペーストして複数のクラスを作成した場合は、全てのクラスで修正する必要があります。
しかし、スーパークラスを継承して、クラスを作成していた場合は、スーパークラスのみを変えることで簡単に修正ができます。
このように、同じアルゴリズムの処理を複数作る時は、「Template Methodパターン」を使って置くことで、共通部分の処理が変更になった場合でも簡単に対処することができます。
「Java言語で学ぶデザインパターン入門」にもありましたが、
抽象クラスの段階で処理の流れを形作るのは大切なことです。
ということを改めて思いました。
##「Template Methodパターン」を使う際の注意
「Template Methodパターン」を使って作成されたサブクラスは、テンプレートとなるスーパークラスで設定されたアルゴリズムをそのまま使用する。
なのでスーパークラスでどのような処理をするのかを理解した上でサブクラスを作成する必要があります。
##Template Methodの例
「Java言語で学ぶデザインパターン入門」にもあった例を使ってクラス図とPythonのコードを作成します。
ヘッダーをつけるメソッドを「open」とし、フッダーをつけるメソッドを「close」とし、文字や文字列を表示するメソッドを「print_string」とし、文字や文字列を5回繰り返して表示するメソッドを「display」とします。
スーパークラスでは、「open」、「close」、「print_string」の3つのメソッドは抽象メソッドで、「display」だけが実装されているものとします。
スーパークラスで実装されている「display」メソッドでは、「open」、「close」、「print_string」の3つのメソッドが使われているものとします。
このクラス図は、PlantUMLというもので記載しています。
私が、書いたPlantUMLのコードは以下のGitHubに記載がありますのでReadMeを読んでお使いください。
template_method.txtです。
https://github.com/sirajirasajiki/design_pattern_uml/tree/master/template_method
PlantUMLのインストール方法と使い方に関しては、後述のappendixに記載しています。
###クラス図を元にPythonで実装
以下に実装したコードを公開しています。Python 3.7で実装しました。
https://github.com/sirajirasajiki/design_pattern_python/tree/master/TemplateMethod
#まとめ
スーパークラスで処理の枠組みを決め、サブクラスで具体的な処理を記載する「Template Methodパターン」について学びました。
#第3章感想
スーパークラスの段階で具体的な処理を入れることで、サブクラスでどのように作成するかをある程度決めることができるので、スーパークラスを作った人以外が実装するときでも、あまり迷わずに実装できるのかなと思いました。
後、今回例が思いつかなかったので、もっと色んなことを知るようにします。
説明で使った例は、後日Pythonで実装しようと思います。
Pythonで実装しました。
#最後に
何か間違っているところがあれば、ご指摘していただけると嬉しいです!
#appendix
##次回の記事
https://qiita.com/sirajirasajiki/items/3a779d3529fbc14af801
##PlantUMLに関するサイト
PlantUMLのインストールの時にお世話になったサイトは以下です。
https://qiita.com/kohashi/items/1d2c6e859eeac72ed926
PlantUMLを書くときにお世話になっているサイトは以下です。
https://qiita.com/ogomr/items/0b5c4de7f38fd1482a48
##Pythonで実装する時に参考にしたもの
Pythonで標準出力で改行しない方法
https://qiita.com/tortuepin/items/4fbf29e42f05cb4b02a5
#更新履歴
2020/3/8 例の追加及び、クラス図、Pythonでの実装を追加