GoFのデザインパターン(Design Pattern)のテンプレートメソッド(template method)のRubyコードを使った紹介記事です。
テンプレートメソッドは、2つのコードのやりたいこと(アルゴリズム)がほとんど同じで、ある一部だけ変えたいようなパターンの時に有効です。
テンプレートメソッドとは?
テンプレートメソッドは次の2つのオブジェクトによって構成されます。
* 骨格としての「抽象的なベースのクラス」 * 実際の処理を行う「サブクラス」
テンプレートメソッドのメリット
* 抽象的なベースのクラス側に、「変わらない基本的なアルゴリズム」を置ける * 抽象的なベースのクラスは「高レベルの処理」を制御することに集中できる * サブクラス側に、「変化するロジック」を置ける * サブクラスは「詳細を埋めること」に集中できる
「高レベルの処理」とは、プログラミング的には「抽象度の高い処理、ロジック的な部分、処理のフレーム」といった言葉に言い換えられると思います。 「詳細を埋める」とは、プログラム的にはレポートの行を書き出すといった具体的な処理を指しています。
サンプルソース
次のようなモデルを使って、テンプレートメソッドについて説明していきます。
* Report(抽象的なベースのクラス): レポートを出力する * HTMLReport(サブクラス): HTMLフォーマットでレポートを出力 * PlaneTextReport(サブクラス): PlanTextフォーマットでレポートを出力
まず、レポートの出力を行うReportクラスです。
Reportクラスには次の4つのメソッドを持っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
次はHTML形式でのレポート出力を行うHTMLReportです。
このクラスは、Reportクラスのメソッドの中でHTML出力の時に変化する3つのメソッドを持っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
最後がPlaneText形式(*****で囲う)での出力を行うPlaneTextReportです。
このクラスは、Reportクラスのメソッドの中でPlaneText形式で出力の際に変化する2つのメソッドを持っています。
1 2 3 4 5 6 7 8 9 10 11 12 | |
コーディングは以上です。続いて結果を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
ベースとしてのReportクラスの機能を持ちつつ、HTML形式とPlaneText形式で出力できていることがわかります。
このサンプルソースはGitHubにも置いています。
コードから読み解く、テンプレートメソッドの特徴
output_lineメソッド => 抽象クラスで具体的な実装をせず、サブクラス側だけ定義することができる output_startメソッド => 抽象クラスで定義して、サブクラスでオーバライドすることができる
オーバーライド (override)とは、「抽象的なベースのクラス」側で定義されたメソッドを「サブクラス」でもう一度定義し直して処理を上書きすること。
テンプレートメソッドの注意点
テンプレートメソッドを適用するときの注意点としては、
「YAGNI = You Aren't Going to Need It.(今必要なことだけ行う)」を徹底する 解決したい問題に絞って単純なコードを書いていくこと
テンプレートメソッドの利用例
オブジェクトを初期化するメソッドinitializeは既存のinitializeをオーバーライドして、自由に初期化処理を行うことができます。
このinitializeは広義でのテンプレートメソッドです。
Special Thanks
変更来歴
12/10 09:00 GitHubへのサンプルソースの設置。導入文の修正
12/11 00:00 書籍へのリンクをAmazon アフィリエイトに変更
12/16 18:40 ソースコードへの説明書きを追加
06/20 10:10 Ruby2.0.0対応、読みづらい部分を修正