新人SEの学習記録

14年度入社SEの学習記録用に始めたブログです。気づけば社会人3年目に突入。

学習記録:デザインパターン

[学習記録] デザインパターン

第3章 Template Method

概要
  • テンプレートとは何か
    • 文字の形に穴があいている薄いプラスチック板
    • ペンでなぞると整った文字を書くことができる
    • 形は統一されるが、どのような文字になるかは使用する筆記具によって決まる
サンプルプログラム

※書籍のサンプルとは変更してあります

AbstractDisplay テンプレートメソッドであるdisplayを実装。その中で使用する抽象メソッドも定義。
MoneyDisplay AbstractDisplayを継承し、メソッドopen, print, closeを実装。
PostCodeDisplay 同上
Main 動作テスト用
  • AbstractDisplay
    • open, print, close, displayというメソッドを持つ抽象クラス。
    • open, print, closeは抽象メソッドで、displayのみ実装を持つ。
public abstract class AbstractDisplay {
	protected abstract void open();
	protected abstract void print();
	protected abstract void close();
	
	protected final void display() {
		open();
		print();
		close();
	}
}
  • MoneyDisplay
    • AbstractDisplayを継承。
    • open, closeで文字列">>>"、"<<<"を表示し、printではカンマ区切りと円マーク付きで金額を表示する。
public class MoneyDisplay extends AbstractDisplay {
	private BigDecimal bd;
	
	public MoneyDisplay(Number number) {
		bd = new BigDecimal(number.toString());
	}
	
	@Override
	protected void open() {
		System.out.println(">>>");
	}

	@Override
	protected void print() {
		System.out.println(NumberFormat.getCurrencyInstance().format(bd));
	}

	@Override
	protected void close() {
		System.out.println("<<<");
	}
}
  • PostCodeDisplay
    • こちらはopen, closeで"==="を表示。printで郵便番号の形式で出力。
public class PostCodeDisplay extends AbstractDisplay {
	String postcode;

	public PostCodeDisplay(int postcode) {
		this.postcode = String.valueOf(postcode); 
	}
	
	@Override
	protected void open() {
		System.out.println("===");
	}

	@Override
	protected void print() {
		System.out.println("〒" + postcode.substring(0, 3) + "-" + postcode.substring(3));
	}

	@Override
	protected void close() {
		System.out.println("===");
	}
}
  • Main
public class Main {

	public static void main(String[] args) {
		AbstractDisplay ad1 = new MoneyDisplay(123456789);
		AbstractDisplay ad2 = new PostCodeDisplay(1234567);
		
		ad1.display();
		ad2.display();
	}
}
>>>
¥123,456,789
<<<
===
〒123-4567
===
登場人物
  • AbstractClassの役
  • ConcreteClassの役
    • AbstractClass役で定義されている抽象メソッドを具体的に実装する
    • 実装したメソッドは、AbstractClass役のテンプレートメソッドから呼び出される
まとめと補足
  • Template Methodパターンを使うと何がいいの?
    • ロジックを共通化することでサブクラス側でアルゴリズムをいちいち記述しなくて済む
    • テンプレートメソッドに誤りがあっても、AbstractClassのテンプレートメソッドを修正するだけでOK
    • ただし、サブクラスの実装では、そのメソッドがどのタイミングで呼び出されるか理解しておく必要
  • 関連しているパターン
    • Factory Methodパターン(4章):TemplateMethodパターンをインスタンス生成に応用
    • Strategyパターン(10章)TemplateMethodパターンでは継承を利用したが、こちらは委譲を利用してプログラムの動作を変更する
  • 補講
    • クラス階層について学ぶとき、サブクラスの視点で考えがち
    • スーパークラスメソッドが利用できる、新しい機能が追加できる、オーバライドで機能を変更できる…
    • スーパークラスの視点で考えると、抽象メソッドが宣言するということはサブクラスにそのメソッドの実装を要請していることになる
    • これをsubclass responsibilityと呼ぶ