2012年11月22日木曜日

Template Methodパターン(テンプレート・メソッド・パターン)

Template Methodパターンは振る舞いに関するパターンのひとつです。

処理の流れは同じなんだけど、一部の処理を作る方法



スーパークラスにおおまかな処理の流れを実装し(抽象クラス、抽象メソッド)
子クラスで一部の違う処理を実装します(クラスの拡張)
・・・無意識に使われているデザインパターンです。


------------------------------------
おおまかな処理の流れのクラス

ファイル名:AbstractDisplay .java
// 抽象クラス
public abstract class AbstractDisplay {
     // サブクラスに実装をまかせる抽象メソッド
    public abstract void open();
    public abstract void print();
    public abstract void close();
    // この抽象クラスで実装しているメソッドdisplay
    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();
    }

    // openとcloseから呼ばれる
    // privateなので、このクラスの中だけで使われる。
    private void printLine() {
        System.out.print("+");
        for (int i = 0; i < width; i++) {
            System.out.print("-");
        }
        System.out.println("+");
    }
}
--------------------------------
メインクラスから使う
ファイル名:Main.java

public class Main {
    public static void main(String[] args) {

        // CharDisplayのインスタンスを1個作る。
        AbstractDisplay d1 = new CharDisplay('H');

         // StringDisplayのインスタンスを1個作る。
        AbstractDisplay d2 = new StringDisplay("Hello, world.");
        AbstractDisplay d3 = new StringDisplay("こんにちは。");

        d1.display();  // d1,d2,d3とも、すべて同じAbstractDisplayのサブクラスのインスタンスだから、
        d2.display();  // 継承したdisplayメソッドを呼び出すことができる。
        d3.display();  // 実際の動作は個々のクラスCharDisplayやStringDisplayで定まる。
    }
}

ポイントは、型はスーパークラスというところ。
実際のインスタンスは子クラスだから、実行時の振る舞いは子クラス。

0 件のコメント:

コメントを投稿









ロリポップ!なら月々105円から

WordPress、MovableTypeなどの簡単インストール、

アクセス解析、ウェブメーラーが標準装備!






プロペシア