1概要

このクイックチュートリアルでは、https://en.wikipedia.org/wiki/Template

method

pattern[template method pattern] – 最も人気のあるhttps://en.wikipedia.org/wiki/Design__Patternsの1つを活用する方法について説明します。[GoF]パターン

ロジックを単一のメソッドにカプセル化することで、複雑なアルゴリズムを簡単に実装できます。


2実装

テンプレートメソッドパターンがどのように機能するかを説明するために、コンピュータステーションを構築することを表す簡単な例を作成しましょう。

パターンの定義を考えると、アルゴリズムの構造はテンプレート

build()

methodを定義する基本クラスで定義されます

public abstract class ComputerBuilder {

   //...

    public final Computer buildComputer() {
        addMotherboard();
        setupMotherboard();
        addProcessor();
        return new Computer(computerParts);
    }

    public abstract void addMotherboard();
    public abstract void setupMotherboard();
    public abstract void addProcessor();

   //...
}


  • ComputerBuilder

    クラスは、マザーボードやプロセッサなど、さまざまなコンポーネントを追加および設定するためのメソッドを宣言することによって、コンピュータの構築に必要な手順の概要を説明します。

ここで、


build()

メソッドはテンプレートメソッド

です。これは、コンピュータパーツを組み立てるためのアルゴリズムのステップを定義し、完全に初期化された

Computer

インスタンスを返します。

上書きされないようにするために、

final

と宣言されています。


3実行中

基本クラスが既に設定されているので、2つのサブクラスを作成して使用しましょう。 「標準」コンピュータを構築するものと、「ハイエンド」コンピュータを構築するものです。

public class StandardComputerBuilder extends ComputerBuilder {

    @Override
    public void addMotherboard() {
        computerParts.put("Motherboard", "Standard Motherboard");
    }

    @Override
    public void setupMotherboard() {
        motherboardSetupStatus.add(
          "Screwing the standard motherboard to the case.");
        motherboardSetupStatus.add(
          "Pluging in the power supply connectors.");
        motherboardSetupStatus.forEach(
          step -> System.out.println(step));
    }

    @Override
    public void addProcessor() {
        computerParts.put("Processor", "Standard Processor");
    }
}

そして、これが

HighEndComputerBuilder

バリアントです。

public class HighEndComputerBuilder extends ComputerBuilder {

    @Override
    public void addMotherboard() {
        computerParts.put("Motherboard", "High-end Motherboard");
    }

    @Override
    public void setupMotherboard() {
        motherboardSetupStatus.add(
          "Screwing the high-end motherboard to the case.");
        motherboardSetupStatus.add(
          "Pluging in the power supply connectors.");
        motherboardSetupStatus.forEach(
          step -> System.out.println(step));
    }

    @Override
    public void addProcessor() {
         computerParts.put("Processor", "High-end Processor");
    }
}

ご覧のとおり、アセンブリプロセス全体について心配する必要はありませんでしたが、個別のメソッドの実装を提供するためだけです。

それでは、実際に見てみましょう。

new StandardComputerBuilder()
  .buildComputer();
  .getComputerParts()
  .forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v));

new HighEndComputerBuilder()
  .buildComputer();
  .getComputerParts()
  .forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v));


4 Javaコアライブラリのテンプレートメソッド

このパターンはJavaコアライブラリで広く使用されています。//docs.oracle.com/javase/7/docs/api/java/util/AbstractSet.html[java.util.AbstractSet]

たとえば、

Abstract List

はhttps://docs.oracle.com/javase/7/docs/api/java/util/List.html[

List

]インタフェースのスケルトン実装を提供します。

テンプレートメソッドの例としては、

addAll()

メソッドがありますが、__finalとして明示的に定義されているわけではありません。

public boolean addAll(int index, Collection<? extends E> c) {
    rangeCheckForAdd(index);
    boolean modified = false;
    for (E e : c) {
        add(index++, e);
        modified = true;
    }
    return modified;
}

ユーザーは

add()

メソッドを実装するだけでいいです。

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

ここでは、与えられたインデックス(リストアルゴリズムのバリアント部分)でリストに要素を追加するための実装を提供するのはプログラマの責任です。


5結論

この記事では、テンプレート・メソッド・パターンとそれをJavaで実装する方法を示しました。

テンプレートメソッドパターンは、コードの再利用と分離を促進しますが、継承を使用します。

いつものように、この記事に示されているすべてのコードサンプルはhttps://github.com/eugenp/tutorials/tree/master/patterns/design-patterns/[GitHubで利用可能]です。