デザインパターン「Template Method」

# はじめに
本投稿は<a href="http://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=sr_1_1?ie=UTF8&qid=1454743284&sr=8-1&keywords=java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80" target="_blank">Java言語で学ぶデザインパターン入門</a>のデザインパターンをまとめた記事です。今回はSingletonパターンになります。
[まとめ一覧はこちら](#design_pattern)

# Template Methodパターン
<p align="center"><img width="442" alt="スクリーンショット 2016-02-14 15.31.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/97335676-5f16-f284-1018-ea189abca239.png"></p>

## Templateとは
###### <a href="https://ja.wikipedia.org/wiki/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88" target="_blank">Wikipedia参照</a>
> 文書などのコンピュータデータを作成する上で雛形となるデータ

とありますが、本書では文字を綺麗に書くためのテンプレート板を例に紹介されています。

異なる色のペンや、筆・クレヨンなどを用いても同じ形の文字になるように、スーパークラスで処理の枠組みを決め、サブクラスで具体的な内容を定めるデザインパターンを***Template Methodパターン***と呼びます。

手続き型プログラミング言語は似た処理を***一つの関数にまとめる***のに対し、オブジェクト指向言語では、自然と似た処理の部分を***１つのクラスとしてまとめている***と思います。この設計はまさにTemplate Methodパターンに準拠していますね。

***似たような流れの処理を共通化したい時***にこのパターンを適応することが多いです。

## Template Methodパターンのクラス図
<p align="center"><img width="230" alt="スクリーンショット 2016-02-14 15.53.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/fcbf5ea6-1b9e-2b79-9944-640f2f0d2849.png"></p>

- AbstractClassで抽象メソッドの宣言、テンプレートメソッドの実装
- ConcreteClassで抽象メソッドの実装

## 具体例
文字・文字列を3回繰り返し表示する簡単な例で紹介していきます

- AbstractClass :[AbstractDisplayクラス](#abstract)
- ConcreteClass
 - [CharDisplayクラス](#concrete_char)(文字表示)
 - [StringDisplayクラス](#concrete_string)(文字列表示)

### Mainクラス
クラスの生成と一緒に渡した文字(列)が、加工されて表示されるようなクラスを作っていきます。

```java:Main.java
public static void main(String[] args) {
		
        //※
		AbstractDisplay cd = new CharDisplay('T');
		AbstractDisplay sd = new StringDisplay("Design Pattern");
		AbstractDisplay sd2 = new StringDisplay("Template Method");
		
		cd.display();
		sd.display();
		sd2.display();	
}
```

異なるサブクラスの生成をスーパークラスに代入しています。
詳しくは[LSP参照(後述)](#lsp)

### <a id="abstract">AbstractClass</a>
文字・文字列を3回繰り返し表示するTemplate Methodを実装しています

```java:AbstractDisplay.java
public abstract class AbstractDisplay {
	public abstract void open();
	public abstract void print();
	public abstract void close();
    //Template Method
	public final void display() {
		open();
		for (int i =0; i < 3; i++) {
			print();
		}
		close();
	}
}
```



### ConcreteClass

<a id="concrete_char">CharDisplayクラス</a>

- 文字の前後に***を付与

```java:CharDisplay.java
public class CharDisplay extends AbstractDisplay {
	private char ch;
	public CharDisplay(char ch) {
		this.ch = ch;
	}
	
	public void open() {
		System.out.print("***");
	}
	public void print() {
		System.out.print(ch);
	}
	public void close() {
		System.out.println("***");
	}

}
```

<a id="concrete_string">StringDisplayクラス</a>

- 文字列の周りを枠線で囲む

```java:StringDisplay.java
public class StringDisplay extends AbstractDisplay {
	private String string;
	private int width;
	public StringDisplay(String string) {
		this.string = string;
		this.width = string.getBytes().length;
	}

	public void open() {
		printLine();

	}
	public void print() {
		System.out.println("|" + string + "|");

	}
	public void close() {
		printLine();

	}
	
	private void printLine() {
		System.out.print("+");
		for (int i = 0; i < width; i++) {
			System.out.print("-");
		}
		
		System.out.println("+");
	}

}
```


## 実行結果

```java
***TTT***
+--------------+
|Design Pattern|
|Design Pattern|
|Design Pattern|
+--------------+
+---------------+
|Template Method|
|Template Method|
|Template Method|
+---------------+
```

このようにスーパクラスのTemplateMethodのロジックで、処理の共通化ができてますね。

# 追記

- メリット
 - スーパークラスにロジックが集中しているので、バグが生じてもTemplateMethodのみを修正すればいい
 - サブクラスの設計が簡潔になる


- デメリット
 - サブクラスの数が増加する
 - 親と子の関係が密接なので、スーパークラスのソースを確認しないと実装が難しい
 - スーパークラスの処理が大きくなると、サブクラスの自由度が減少する


## <a id="lsp">LSP(The Liskov Substitution Principle)</a>
オブジェクト指向プログラミングにおける派生型の定義の一種で、リスコフの置換原則ともいわれます。
簡単に言うとTemplate Methodのように、スーパークラスとサブクラスを定義するとき、サブクラスはスーパークラスを置き換えることができなければならないという原則です。

Aクラスに依存するBクラスが存在するとする。
BクラスをのサブクラスB', やさらにサブクラスB''に置き換えても正常の動作しなければならないということです。

### 例えば...
<dl>
 <dt>サブクラスでオーバーライドされた結果、動作が意図しないものに変わってはならない</dt>
 <dd>・公開する必要がないメンバのアクセス修飾子は、privateにする</dd>
 <dd>・オーバーライドをする必要がなければ、final修飾子のような宣言をする(Java)</dd><br>
 <dt>結果がスーパークラスの意図から外れてしまうようなオーバーライドはしない</dt><br>
 <dt>クラスAはサブクラスB'やB"を判定して処理をするような設計であってはならない</dt>
</dl>

まとめると

1. 同じスーパークラス(インタフェース)を持っていて、違うオブジェクトでも同じように扱える
2. オブジェクトによって動作は異なる
3. クライアントからは同じ動作をしているように見えなければならない

の条件を守った設計であれば、継承関係でバグが発生しなくうまくいくということなんですね。

参考

- <a href="http://think-on-object.blogspot.jp/2011/11/liskov-substitution-principle-lsp-ok.html" target="_blank">リスコフの置換原則参照</a>
- <a href="http://marupeke296.com/OOD_No7_LiskovSubstitutionPrinciple.html" target="_blank">親の決まりを子が破っちゃいけない原則：LSP</a>


### サンプルコードについて

以下のレポジトリにソースコードをアップしてあります。

[shoheiyokoyama/design-pattern_java](https://github.com/shoheiyokoyama/design-pattern_java/tree/master/TemplateMethod)

# <a id="design_pattern">デザインパターン</a>

- 生成に関するパターン
 - Abstract factory
 - Builder
 - <a href="http://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca" target="_blank">Factory Method</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/61826e158b3c4a259065" target="_blank">Prototype</a>
 - <a href="http://qiita.com/shoheiyokoyama/items/c16fd547a77773c0ccc1" target="_blank">Singleton</a>
- 構造に関するパターン
 - <a href="http://qiita.com/shoheiyokoyama/items/bd1c692db480b640c976" target="_blank">Adapter</a>
 - Bridge
 - Composite
 - Decorator
 - Facade
 - Flyweight
 - Proxy
- 振る舞いに関するパターン 
 - Chain of responsibility
 - Command
 - Interpreter
 - <a href="http://qiita.com/shoheiyokoyama/items/3f42d0057d9d5a861039" target="_blank">Iterator</a>
 - Mediator
 - Memento
 - <a href="http://qiita.com/shoheiyokoyama/items/d4b844ed29f84a80795b" target="_blank">Observer</a>
 - State
 - Strategy
 - <a href="http://qiita.com/shoheiyokoyama/items/c2ce16b4f492cd014d50" target="_blank">Template Method</a>
 - Visitor

# 参考文献
- <a href="http://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=sr_1_1?ie=UTF8&qid=1454743284&sr=8-1&keywords=java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80" target="_blank">Java言語で学ぶデザインパターン入門</a> 
- <a href="http://think-on-object.blogspot.jp/2011/11/liskov-substitution-principle-lsp-ok.html" target="_blank">リスコフの置換原則参照</a>
- <a href="http://marupeke296.com/OOD_No7_LiskovSubstitutionPrinciple.html" target="_blank">親の決まりを子が破っちゃいけない原則：LSP</a>