連載
.NETで始めるデザインパターン

第4回 リファクタリングにより導き出すTemplate Methodパターン

太陽システム株式会社 中西 庸文
Microsoft MVP 2005 - Solutions Architect)
2005/04/23
Page1 Page2 Page3 Page4


Back Issue
1
.NET開発におけるデザインパターンの有用性
2
うまくデザインパターンを使うための心得
3
リファクタリングにより導き出すStrategyパターン
4
リファクタリングにより導き出すTemplate Methodパターン
5
Compositeパターンを導き出すための準備
6
リファクタリングにより導き出すCompositeパターン
7
デザインパターンの落とし穴

 前回は、XP(エクストリーム・プログラミング)の「5つの価値」の内容(コミュニケーション、シンプル、フィードバック、勇気、敬意)をプレーン・テキスト形式やHTML形式で出力できるサンプル・プログラムを作成し、それをリファクタリングすることでStrategyパターンを導き出した。このリファクタリングは「Replace Conditional Logic with Strategy(K)」(Strategyパターンによる条件ロジックの置き換え)と呼ばれると紹介した。

 今回は、前回のサンプル・プログラムに対してさらにリファクタリングを加えていく。実は前回までのリファクタリングは、今回行うリファクタリングのための布石にすぎなかったのだ。引き続きリファクタリングを行って、さらなるデザインパターンを導いていくことにしよう。

 なお本稿の開発手順は、すべてテスト駆動開発(TDD:Test-Driven Development)のスタイルで行う(テスト駆動開発については、「テスト駆動開発ツール最前線」を参照されたい)。前回同様、本稿のサンプル・コードは、追加したコードは青色、削除したコードは赤色で表現している。

■リファクタリング前の設計

 まず、現状のStrategyパターン部分のコード(抽象クラスであるTextFormatterクラスと、その派生クラスであるPlainTextFormatterクラスとHtmlTextFormatterクラス)を以下に再掲する。

 今回のリファクタリングでは、これら以外のテスト・コードおよびXpValuesクラスには変更を加えないので割愛する。これについては前回のコードを参照いただきたい。

using System;

namespace DesignPatterns.Core.TemplateMethod
{
  // TextFormatterクラス
  public abstract class TextFormatter
  {
    // 「価値」を出力する
    public abstract string Format(XpValues xpValues);

    // タイトルを取得する
    protected string GetTitleFor(XpValues xpValues)
    {
      return xpValues.Name + "の" + xpValues.Count.ToString() + "つの価値";
    }
  }
}
TextFormatterクラス(C#)
 
using System;
using System.Text;

namespace DesignPatterns.Core.TemplateMethod
{
  // PlainTextFormatterクラス
  public class PlainTextFormatter : TextFormatter
  {
    // 「価値」を出力する
    public override string Format(XpValues xpValues)
    {
      StringBuilder builder = new StringBuilder();
      builder.Append(GetTitleFor(xpValues) + "\r\n");
      foreach (string xpValue in xpValues)
        builder.Append("・" + xpValue + "\r\n");
      return builder.ToString();
    }
  }
}
PlainTextFormatterクラス(C#)
 
using System;
using System.Text;

namespace DesignPatterns.Core.TemplateMethod
{
  // HtmlTextFormatterクラス
  public class HtmlTextFormatter : TextFormatter
  {
    // 「価値」を出力する
    public override string Format(XpValues xpValues)
    {
      StringBuilder builder = new StringBuilder();
      builder.Append("<p>" + GetTitleFor(xpValues) + "</p>\r\n");
      builder.Append("<ul>\r\n");
      foreach (string xpValue in xpValues)
        builder.Append("<li>" + xpValue + "\r\n");
      builder.Append("</ul>\r\n");
      return builder.ToString();
    }
  }
}
HtmlTextFormatterクラス(C#)

 ここまでのコードは、プレーン・テキスト形式の出力アルゴリズム(=Strategy:戦略)をPlainTextFormatterクラスに、HTML形式の出力アルゴリズムをHtmlTextFormatterクラスに、それぞれカプセル化しておき、利用者にはポリモーフィズムにより、これらの基本クラスであるTextFormatterクラスのみを通じて各出力アルゴリズムを使用させるというStrategyパターンになっている。

■リファクタリングから Template Method パターンへ

 前回のリファクタリングの結果としてStrategyパターンが導かれた。しかし、これらのコードには重複するアルゴリズムが存在している。以降のリファクタリングでは、この重複するアルゴリズムを除去していくことにしよう。

●Template Methodの形成

 PlainTextFormatterクラスのFormatメソッドと、HtmlTextFormatterクラスのFormatメソッドに注目してほしい。これらのメソッドを比較してみると、次のように、テキストの各パートを順番に出力するという点において、アルゴリズムが非常に似ていることに気付くだろう。

  • HtmlTextFormatterクラスのFormatメソッド
    • タイトルの出力
    • ヘッダの出力
    • 価値の出力
    • フッタの出力
  • PlainTextFormatterクラスのFormatメソッド
    • タイトルの出力
    • 価値の出力

 PlainTextFormatterクラスのFormatメソッドには、「ヘッダの出力」および「フッタの出力」が必要ないだけで、そのアルゴリズムはHtmlTextFormatterクラスのFormatメソッドと重複していると見なすことができる。

 このような重複するアルゴリズムをそのままにしておけば、新しい形式で「価値」を出力するようなTextFormatterクラスの派生クラスを追加した際には、同じようなアルゴリズムのコードがさらに増えることになる。

 そこで、基本クラスであるTextFormatterクラスでは、XPの価値を出力するための各ステップをそれぞれ個別のメソッドとして定義し、Formatメソッドでそれらのメソッドを呼び出すようにする。また、出力形式によって振る舞いの異なるメソッドは抽象メソッドにし、派生クラスでその振る舞いをオーバーライドできるようにする。

 このようにすれば、アルゴリズムの骨組みとなる固定部分は基本クラス側で共通化され、可変部分は派生クラス側で拡張できる。コードの重複はなくなり、新しい出力形式への対応も容易になるはずだ。

 これは「Template Methodパターン」の目的と一致する。書籍『オブジェクト指向における再利用のためのデザインパターン』では、Template Methodパターンの目的は次のように記述されている。

1つのオペレーションにアルゴリズムのスケルトンを定義しておき、その中のいくつかのステップについては、サブクラスでの定義に任せることにする。Templete Methodパターンでは、アルゴリズムの構造を変えずに、アルゴリズム中のあるステップをサブクラスで再定義する。

 「Template Method」とは、その名のとおりアルゴリズムの骨組みを定義したメソッドのことだ。

 それでは、重複したアルゴリズムからTemplate Methodパターンを導くためのリファクタリングの手順を紹介しよう。


 INDEX
  .NETで始めるデザインパターン
  第4回 リファクタリングにより導き出すTemplate Methodパターン
  1.リファクタリングから Template Method パターンへ
    2.リファクタリング:「Compose Method(K)」
    3.リファクタリング:「メソッドの引き上げ(F)」
    4.リファクタリングの結果
 
インデックス・ページヘ  「.NETで始めるデザインパターン」

TechTargetジャパン

Insider.NET フォーラム 新着記事
  • Kinectが切り開く“夢の近未来” (2012/2/2)
     日本を含めた世界中でKinect for Windowsセンサー商用版とSDK正式版がリリース。未来のコンピューティングはどう変化するのか?
  • 3つの視点でネイティブと.NETの適材適所を考察 (2012/1/31)
     アプリ開発は「ネイティブ」と「.NET」、どちらが最良? その問いには「適材適所」と答えるしかない。では、“適所”は一体どこかを考察する
  • SQL Azure Data Sync入門 (2012/1/30)
     SQL Azure/SQL Serverデータベース間のデータ同期を簡単に実現するサービスとは? その仕組みや使用手順を解説
  • Windows Phoneアプリ市場の現状を分析する (2012/1/27)
     Windows Phone のアプリ・ストアに日々登録されている多種多様なアプリ。カテゴリ別のアプリ数は? 市場の現状を明らかにする

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

- PR -
@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH