JavaでTemplateMethodパターン

# はじめに
[GoF](https://ja.wikipedia.org/wiki/ギャング・オブ・フォー_(情報工学))のデザインパターンを紹介している[『増補改訂版 Java言語で学ぶデザインパターン入門』](https://www.amazon.co.jp/増補改訂版Java言語で学ぶデザインパターン入門-結城-浩/dp/4797327030/ref=pd_lpo_sbs_14_t_0?_encoding=UTF8&psc=1&refRID=2ZE4GPYNN55JGDR5QMHP)を読んで、学んだ内容についてまとめます。

# TemplateMethodパターン
## TemplateMethodとは
**処理の骨組みをスーパークラスで定義し、具体的な実装についてはサブクラスで定義するパターンのこと**を**TemplateMethodパターン**と言います。
この内、スーパークラスで「**処理の骨組みを定義しているメソッド**」が**TemplateMethod**になります。

## 登場人物
TemplateMethodパターンで使用するのは以下のクラス図に登場するクラスです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/278934/da16c443-839a-5147-1f3d-574f1ed5cbf6.png)

### 抽象クラス
- **AbstractClass**  
**テンプレートメソッドを実装するクラスです。**  
テンプレートメソッド内で呼び出すメソッドについても宣言を行いますが、実装についてはサブクラスの`ConcreateClass`で行います。  
そのため、テンプレートメソッド以外のメソッドは抽象メソッドとなります。

### 実装クラス
- **ConcreateClass**  
**テンプレートメソッド内で呼び出されている抽象メソッドを実装するクラスです。**  
ここで実装したメソッドがスーパークラスである`AbstractClass`から呼び出されます。


## 具体例
具体例として、「**手順書**」と「**作業Aの手順書**」、「**作業Bの手順書**」をもとに説明します。

### 抽象クラス
- **AbstractManualクラス**  
AbstractManual(手順書)クラスは抽象クラスで、作業手順の骨組みを実装します。  
ここでは**`operation()`メソッド**が作業手順の骨組みを実装しているメソッド(templateMethod)になります。  
その他の`start()`メソッド、`work()`メソッド、`end()`メソッドに関しては宣言を行い、`operation()`メソッド内で呼び出しを行なっていますが、実装は行なっておらず、具体的な処理についてはサブクラスの`OperationAManual.class`と`OperationBManual.class`で定義します。

```java:AbstractManual.java
package templateMethod;

public abstract class AbstractManual{
	public abstract void start();

	public abstract void work();

	public abstract void end();

	public final void operation() {
		start();
		for (int i = 0; i < 3; i++) {
			work();
		}
		end();
	}
}
```

### 実装クラス
- **OperationAManualクラス**  
抽象メソッドの`start()`、`work()`、`end()`を実装しています。  
コンストラクタで**文字**を受け取り`work()`メソッドで出力を行っています。

```java:OperationAManual.java
package templateMethod;

public class OperationAManual extends AbstractManual {
	private char ch;

	public OperationAManual(char ch) {
		this.ch = ch;
	}

	@Override
	public void start() {
		System.out.println("<<作業A開始>>");
	}

	@Override
	public void work() {
		System.out.println(ch + "を処理しています");
	}

	@Override
	public void end() {
		System.out.println("<<作業A終了>>");
	}
}
```

- **OperationBManualクラス**  
`OperationAManual.class`と同様に抽象メソッドの`start()`、`work()`、`end()`を実装していますが、**実装の内容については異なっています。**  
コンストラクタで**文字列**を受け取り、`work()`メソッドで出力を行っています。

```java:OperationBManual.java
package templateMethod;

public class OperationBManual extends AbstractManual {
	private String string;

	public OperationBManual(String string) {
		this.string = string;
	}

	@Override
	public void start() {
		System.out.println("**作業B開始**");
	}

	@Override
	public void work() {
		System.out.println(string + "を処理しています");
	}

	@Override
	public void end() {
		System.out.println("**作業B終了**");
	}
}
```

### 実行クラス
- **Mainクラス**  
`OperationAManual`と`OperationBManual`のインスタンスを生成し、TemplateMethodの`operation()`を呼び出しています。  

```java:Main.java
package templateMethod;

public class Main {
	public static void main(String[] args) {
		AbstractManual d1 = new OperationAManual('F');
		AbstractManual d2 = new OperationBManual("HelloWorld");
		d1.operation();
		d2.operation();
	}
}
```
### 実行結果
`Main.java`を実行した結果は以下になります。
同様の`operation()`を呼び出しましたが、異なる出力がされていることが確認できます。

```:実行結果
<<作業A開始>>
Fを処理しています
Fを処理しています
Fを処理しています
<<作業A終了>>
**作業B開始**
HelloWorldを処理しています
HelloWorldを処理しています
HelloWorldを処理しています
**作業B終了**
```

## メリット
TemplateMethodパターンを活用することで、処理の骨組みを共通化できます。
このようにすることで複数の作業者が各々好き勝手に処理の骨組みから作成を行い、一律にすべき部分が一律になっていない、ということが防げます。

# まとめ
処理の骨組みを規定するTemplateMethodパターンに関して学びました。
以下でサンプルコードをアップしていますのでよろしければ参考にどうぞ。

- [TemplateMethodサンプルコード](https://github.com/masayuki777/study/tree/master/DesignPatterns/03_TemplateMethod)

また、他のデザインパターンに関しては以下でまとめていますので、こちらも参考にどうぞ。

- [[随時更新]Javaでデザインパターンまとめ](https://qiita.com/mk777/items/4e13505b654fc21c76a2)

# 参考文献
- [増補改訂版 Java言語で学ぶデザインパターン入門](https://www.amazon.co.jp/増補改訂版Java言語で学ぶデザインパターン入門-結城-浩/dp/4797327030/ref=pd_lpo_sbs_14_t_0?_encoding=UTF8&psc=1&refRID=2ZE4GPYNN55JGDR5QMHP)