デザインパターン入門Template Methodパターンについて

2023/03/05に公開
  1. Template Methodパターンとは何か?
    • 定義と概要
    • パターンの利点
  2. Template Methodパターンの実装
    • 抽象クラスと具象クラスの役割
    • Template Methodメソッドの実装
  3. Template Methodパターンの具体例
    • ゲームのキャラクター生成プログラム
    • コードの解説
  4. Template Methodパターンの利用例
    • Webアプリケーション開発における利用例
    • 利用するメリット
  5. Template Methodパターンのまとめ
    • Template Methodパターンの利点と欠点
    • 適用すべき場合

1. Template Methodパターンとは何か?

Template Methodパターンは、オブジェクト指向プログラミングにおいて、振る舞いを共通化するためのパターンの1つです。このパターンは、抽象的な処理を定義し、その処理の中で個別の処理を呼び出すことで、振る舞いを共通化します。

このパターンは、以下のような場合に使用されます。

  • 複数のクラスで似たような処理を実装したい場合
  • 決まった手順で処理を実行したい場合
  • 共通のインターフェースで処理を実行したい場合

Template Methodパターンは、抽象クラスに共通の処理を定義することによって実現されます。抽象クラスには、テンプレートメソッドと呼ばれる共通の処理があり、具象クラスはテンプレートメソッドをオーバーライドして個別の処理を実装します。

このパターンの利点は、処理の共通化によってコードの重複を避けることができることです。また、処理の流れが明確になるため、コードの可読性が向上し、保守性も高くなります。しかし、個別の処理が多い場合は、テンプレートメソッドが複雑になり、メンテナンスが困難になる可能性があることに注意する必要があります。

2. Template Methodパターンの実装

Template Methodパターンの実装には、抽象クラスと具象クラスを使用します。抽象クラスにはテンプレートメソッドと呼ばれる抽象メソッドが定義されています。具象クラスは、このテンプレートメソッドをオーバーライドし、実装を行います。

以下は、JavaでのTemplate Methodパターンの実装例です。まずは抽象クラスを定義します。

abstract class AbstractClass {
    //テンプレートメソッド
    public final void templateMethod() {
        System.out.println("Step 1");
        primitiveOperation1();
        System.out.println("Step 2");
        primitiveOperation2();
        System.out.println("Step 3");
    }

    //抽象メソッド1
    protected abstract void primitiveOperation1();

    //抽象メソッド2
    protected abstract void primitiveOperation2();
}

この抽象クラスには、テンプレートメソッドと呼ばれるメソッドが定義されています。このメソッドでは、複数のステップが定義されており、各ステップで抽象メソッドが呼び出されます。

具象クラスでは、抽象メソッドを実装することで、テンプレートメソッドを完成させます。

class ConcreteClass extends AbstractClass {
    //抽象メソッド1の実装
    @Override
    protected void primitiveOperation1() {
        System.out.println("ConcreteClass primitiveOperation1");
    }

    //抽象メソッド2の実装
    @Override
    protected void primitiveOperation2() {
        System.out.println("ConcreteClass primitiveOperation2");
    }
}

この具象クラスでは、抽象メソッド1と2を実装しています。これによって、テンプレートメソッドを完成させることができます。

実際にテンプレートメソッドを呼び出す場合は、以下のように行います。

AbstractClass abstractClass = new ConcreteClass();
abstractClass.templateMethod();

3. Template Methodパターンの具体例

ここでは、ゲームのキャラクターの移動を例に、Template Methodパターンを使った具体例を紹介します。

まず、以下のようなCharacterクラスがあるとします。

abstract class Character {
    protected int x;
    protected int y;

    public void move() {
        // ここで実装する
    }
}

このCharacterクラスを継承した、具体的なキャラクタークラスを作成します。ここでは、戦士(Warrior)クラスと魔法使い(Wizard)クラスを作成します。

class Warrior extends Character {
    @Override
    public void move() {
        System.out.println("戦士が走って移動しました。");
        this.x += 5;
        this.y += 5;
    }
}

class Wizard extends Character {
    @Override
    public void move() {
        System.out.println("魔法使いが飛んで移動しました。");
        this.x += 10;
        this.y += 10;
    }
}

戦士は走って移動し、魔法使いは飛んで移動するという違いがあります。

次に、Template Methodパターンを使って、キャラクターが移動する際に必ず実行される、共通の処理をまとめます。

abstract class Character {
    protected int x;
    protected int y;

    public void move() {
        System.out.println("移動前の準備をします。");
        moveImpl();
        System.out.println("移動後の後始末をします。");
    }

    protected abstract void moveImpl();
}

class Warrior extends Character {
    @Override
    protected void moveImpl() {
        System.out.println("戦士が走って移動しました。");
        this.x += 5;
        this.y += 5;
    }
}

class Wizard extends Character {
    @Override
    protected void moveImpl() {
        System.out.println("魔法使いが飛んで移動しました。");
        this.x += 10;
        this.y += 10;
    }
}

Characterクラスに移動前と移動後に共通の処理を追加し、具体的な移動処理はサブクラスに実装させるようにしました。

これにより、どのキャラクターも移動前に共通の処理を行い、移動後に共通の処理を行うことができます。また、具体的な移動方法は各サブクラスで実装できるため、柔軟な拡張が可能になります。

このように、Template Methodパターンは共通の処理と具体的な処理を分離することで、コードの重複を減らし、柔軟な拡張性を持たせることができます。

4. Template Methodパターンの利用例

Template Methodパターンは、フレームワークやライブラリでよく使われます。具体的には、以下のような場面で利用されます。

  • Webアプリケーションのフレームワークでのコントローラーの実装
  • ゲームフレームワークでのゲームループの実装
  • データベースアクセスライブラリでのデータベースアクセスメソッドの実装

これらの場面では、フレームワークやライブラリが提供するクラスやメソッドを使いながら、ユーザーが独自の処理を実装できるようになっています。フレームワークやライブラリが提供するクラスやメソッドがTemplate Methodであり、ユーザーが独自の処理を実装する部分が具象サブクラスであると言えます。

また、Template Methodパターンは、JUnitなどのテストフレームワークでもよく使われます。テストの実行順序や前処理、後処理などの決まった処理をテストフレームワークが提供し、ユーザーがテストの具体的な内容を実装することで、テストを実行することができます。

Template Methodパターンは、プログラミングにおいて非常に重要なパターンの1つです。フレームワークやライブラリの実装や、JUnitなどのテストフレームワークの使用などで、よく使われるパターンであるため、しっかりと理解しておくことが大切です。

5. Template Methodパターンのまとめ

Template Methodパターンは、抽象クラスに共通の処理を実装し、派生クラスに個別の処理を実装させることで、アルゴリズムの構造を変えずに処理の流れをカスタマイズできるデザインパターンです。

このパターンを適用することで、処理の流れを固定することができ、柔軟性が高くなります。また、共通の処理を抽象クラスに実装することで、処理の共通化が実現できます。

しかし、Template Methodパターンは、処理の流れが決まっている場合に限定されます。また、処理の流れが複雑になる場合には、パターンを適用することが困難になる場合もあります。

Template Methodパターンは、コードの再利用性を高め、メンテナンス性を向上させることができるため、大規模なプロジェクトで使用することが多いです。

Discussion