TanukiEngineerの1歩ずつ進もうよ!

まだまだ駆け出しエンジニアの学習メモ

デザインパターン:Template Method(テンプレートメソッド)パターン

Template Methodパターンとは

  • Template Methodパターンは、テンプレートの機能を持つパターンです。
  • スーパークラスの方にテンプレートとなるメソッドが定義されています。
  • その定義の中では抽象メソッドが使われています。
  • このため、スーパークラスのプログラムを読んでいるだけでは、最終的にどんな処理をすることになるかは分かりません。
  • わかることは、抽象メソッドをどのように呼び出しているか、ということだけです。
  • 抽象メソッドを実際に実装するのはサブクラスです。
  • サブクラスの側でメソッドを実装すれば、具体的な処理が決定します。
  • 異なるサブクラスが異なる実装を行えば、異なる処理が行われます。
  • しかし、どのサブクラスでどのような実装をしたとしても、処理の大きな流れはスーパークラスで組み立てたとおりになります。
  • このように、スーパークラスで処理の枠組みを定め、サブクラスでその具体的な内容を定めるようなデザインパターンを、「Template Methodパターン」と呼びます。

Template Methodパターンを使うメリットについて

ロジックが共通化できる

  • スーパークラスのテンプレートメソッドでアルゴリズムが記述されているので、サブクラス側ではアルゴリズムをいちいち記述する必要がなくなります。
  • もし、Template Methodパターンを使わず、複数のクラスにロジック部分をコピペしていると、バグが発見されたときに、ロジックが書かれているすべてのクラスを修正しなければならなくなります。
    Template Methodパターンでプログラミングしていれば、テンプレートメソッドに誤りが発見された場合は、テンプレートメソッドのみ修正すればよいことになります。

サンプルプログラム

クラス一覧

名前 説明
Shopping.java メソッドtoShoppingのみ実装されている抽象クラス
OnlineShop.java メソッドchooseProduct, goToCashRegister, Payを実装しているクラス
RealStore.java メソッドchooseProduct, goToCashRegister, Payを実装しているクラス
Main.java 動作テスト用のクラス

クラス図

f:id:TanukiEngineer:20210211094440p:plain
クラス図_TemplateMethodのサンプル

Shopping.java

public abstract class Shopping {
    public abstract void chooseProduct();
    public abstract void goToCashRegister();
    public abstract void pay();
    public void toShopping() {
        chooseProduct();
        goToCashRegister();
        pay();
    }
}

RealStore.java

public class RealStore extends Shopping {
    private String product;
    public RealStore(String product) {
        this.product = product;
    }

    @Override
    public void chooseProduct() {
        System.out.println("***リアル店舗でお買い物***\n");
        System.out.println("陳列棚から「" + product + "」を選びました。");
    }
    
    @Override
    public void goToCashRegister() {
        System.out.println("レジに並びます。\n人が少ない列に並びました。");
    }
    
    @Override
    public void pay() {
        System.out.println("端末に電子マネーのカードをかざして支払いをしました。\n");
    }
}

OnlineShop.java

public class OnlineShop extends Shopping {
    private String product;
    public OnlineShop (String product) {
        this.product = product;
    }
    
    @Override
    public void chooseProduct() {
        System.out.println("***ネットショッピング***\n");
        System.out.println("商品リストから「" + product + "」を選びました。");
    }
    
    @Override
    public void goToCashRegister() {
        System.out.println("レジへ行くボタンを押下しました。");
    }
    
    @Override
    public void pay() {
        System.out.println("クレジットカードで支払いをしました。\n");
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Shopping sh1 = new RealStore("アイスクリーム");
        Shopping sh2 = new OnlineShop("地方の名産品");
    
        sh1.toShopping();
        sh2.toShopping();
    }
}

実行結果

***リアル店舗でお買い物***

陳列棚から「アイスクリーム」を選びました。
レジに並びます。
人が少ない列に並びました。
端末に電子マネーのカードをかざして支払いをしました。

***ネットショッピング***

商品リストから「地方の名産品」を選びました。
レジへ行くボタンを押下しました。
クレジットカードで支払いをしました。
参考:詳しくは、以下の書籍を参照してください
  • 「補講:クラス階層と抽象クラス」も参考になります
  • 練習問題もあります

増補改訂版Java言語で学ぶデザインパターン入門 | 結城 浩 |本 | 通販 | Amazon