Template Methodパターン

# Template Methodパターン
## 0. はじめに
この記事では、Template Methodパターンについて、以下の3点に分けて説明します。

- 定義と利点
Template Methodパターンの概要とその利点について説明します。
- 主要なコンポーネント
パターンの主要な構成要素について詳しく解説します。
- 実装例
実際にJavaでTemplate Methodパターンを使ったコード例を紹介し、どのように実装するのかを説明します。

## 1. 定義と利点
Template Methodパターンは、スーパークラスでアルゴリズムの「枠組み」を定義し、その中の一部の処理をサブクラスで「具体的な内容」として実装させるデザインパターンです。このパターンにより、アルゴリズムの基本的な流れは変更せずに、個々の処理だけをサブクラスで変更できるようになります。

このパターンを使用すると、以下のような利点があります。
- コードの再利用性: アルゴリズムの枠組みをスーパークラスにまとめることで、共通の処理部分を再利用できます
- 拡張性: サブクラスで詳細部分を変更・追加できるため、新たな処理を加えることが容易になります
- 一貫性の維持: アルゴリズムの流れや順序がスーパークラスで決まっているため、異なるサブクラスでも同じ流れで処理を行うことができます。これにより、コードの一貫性を保つことができます
- 管理の容易さ: アルゴリズムの変更があった場合、スーパークラスで修正するだけで全てのサブクラスに反映されるため、メンテナンスが容易です


例えば、Webページを生成するアルゴリズムを考えた場合、テンプレートメソッドパターンを使うと、ページの「基本的な構成」はスーパークラスに実装し、ページの「具体的な内容」や「レイアウト」をサブクラスに実装することができます。これにより、基本構造は共通に保ちながら、ページの内容やデザインを柔軟に変更できます。

Template Methodパターンは、特にアルゴリズムの骨組みを変更することなく、具体的な処理部分だけを変更したい場合に非常に有効です。

## 2. 主要なコンポーネント
Template Methodパターンは、次の主要なコンポーネントから構成されています。

- **AbstractClass（抽象クラス）**
  - アルゴリズムを記載します
  - 抽象メソッドを宣言します

- **ConcreteClass（具象クラス）**
  - 抽象メソッドの具体的な処理を実装します

## 3. 実装例
実装例ではクラス図とコードの2点に分けて記載します。

### クラス図
Template Methodパターンのクラス図を示します。この図では、抽象クラスと具象クラスの関係が示されています。

```plantuml
@startuml
class AbstractClass {
    method1()
    method2()
    method3()
    templateMethod()
}

class ConcreteClass {
    method1()
    method2()
    method3()
}

AbstractClass <|-- ConcreteClass
@enduml
```
### コード
以下はTemplateMethodパターンを実際に実行するためのコードです。
```java
// AbstractDisplay.java
// 抽象クラス①
public abstract class AbstractDisplay {
  protected abstract void open();
  protected abstract void print();
  protected abstract void close();
  // final修飾子によりサブクラスでアルゴリズムをオーバーライドさせない
  public final void display() {
    open();
    for (int i = 0; i < 5; i++) {
      print();
    }
    close();
  }
}


// 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(">>");
  }
}


// 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("+");
    System.out.print("+");
    for (int i = 0; i < width; i++) {
      System.out.print("-");
    }
    System.out.println("+");
  }
}


// TemplateMethodTest.java
// 実行コードを記載
public class  TemplateMethodTest {
  public static void main(String[] args) {
    AbstractDisplay d1 = new CharDisplay('H');
    AbstractDisplay d2 = new StringDisplay("Hello, world.");
    AbstractDisplay d3 = new StringDisplay("こんにちは。");
    d1.display();
    d2.display();
    d3.display();
  }
}
```
## 参考文献
この記事は以下の情報を参考にして執筆しました。
[増補改訂版 Java言語で学ぶデザインパターン入門](https://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?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)