はじめに

GoFのデザインパターンを紹介している『増補改訂版 Java言語で学ぶデザインパターン入門』を読んで、学んだ内容についてまとめます。


TemplateMethodパターン


TemplateMethodとは

処理の骨組みをスーパークラスで定義し、具体的な実装についてはサブクラスで定義するパターンのことTemplateMethodパターンと言います。

この内、スーパークラスで「処理の骨組みを定義しているメソッド」がTemplateMethodになります。


登場人物

TemplateMethodパターンで使用するのは以下のクラス図に登場するクラスです。

image.png


抽象クラス



  • AbstractClass

    テンプレートメソッドを実装するクラスです。

    テンプレートメソッド内で呼び出すメソッドについても宣言を行いますが、実装についてはサブクラスのConcreateClassで行います。

    そのため、テンプレートメソッド以外のメソッドは抽象メソッドとなります。


実装クラス



  • ConcreateClass

    テンプレートメソッド内で呼び出されている抽象メソッドを実装するクラスです。

    ここで実装したメソッドがスーパークラスであるAbstractClassから呼び出されます。


具体例

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


抽象クラス



  • AbstractManualクラス

    AbstractManual(手順書)クラスは抽象クラスで、作業手順の骨組みを実装します。

    ここではoperation()メソッドが作業手順の骨組みを実装しているメソッド(templateMethod)になります。

    その他のstart()メソッド、work()メソッド、end()メソッドに関しては宣言を行い、operation()メソッド内で呼び出しを行なっていますが、実装は行なっておらず、具体的な処理についてはサブクラスのOperationAManual.classOperationBManual.classで定義します。


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()メソッドで出力を行っています。


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()メソッドで出力を行っています。


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クラス

    OperationAManualOperationBManualのインスタンスを生成し、TemplateMethodのoperation()を呼び出しています。



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パターンに関して学びました。

以下でサンプルコードをアップしていますのでよろしければ参考にどうぞ。

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


参考文献