Template Method パターンを使うならちゃんと使おう

Template Method パターンは差分プログラミングなんかを行う上でわりと便利なこともありますが、使ってるつもり?で使えていない場合を見かけたりします。たとえばこんな感じ。

スーパークラス

public abstract class AbstractClass {

    // サブクラスを判別するためのコード値を返す
    protected abstract String getCode();

    public abstract void execute();

    protected void executeCore() {
        switch (getCode()) {
            case "hogehoge":
                // サブクラス固有の処理を実装
                break;
            case "fugafuga":
                // サブクラス固有の処理を実装
                break;
            default:
            // 略
        }
        // 共通処理の実装
    }
}

サブクラス

public class SubClass1 extends AbstractClass {

    @Override
    protected String getCode() {
        return "hogehoge";
    }

    @Override
    public void execute() {
        // なんか処理

        // 共通処理の呼び出し
        executeCore();
    }
}

こんな感じのサブクラスがいくつかあると思ってください。

サブクラスからコード値的なものを返す抽象メソッドを定義し、スーパークラスでその値で個別処理を実装するようになっています。はい、逆ですね。スーパークラスがサブクラスのことを知る必要はないはずです。スーパークラスはこんな感じにすべきです。

public abstract class AbstractClass {

    // サブクラスで固有の処理を実装
    // 必須でなければ非 abstract にしても
    protected abstract void executeAdditional();

    public abstract void execute();

    protected void executeCore() {

        executeAdditional();

        // 共通処理の実装
    }
}

メソッド名とかはあれなのでちゃんと適切な名前を考えましょう。

さらにいえばサブクラスが必ず executeCore() を呼び出すのであればサブクラスには execute() メソッドではなく executeAdditional() メソッドだけ実装させるようにするとか、そもそも継承させる必要ないんじゃとかまぁいろいろあるかとは思います。 Template Method パターンを使うなら、サブクラスには拡張ポイントだけ提供するのがいいんじゃないでしょうか。

わかってる人には何を今更でしょうけど結構最近なんかこういうコードを見かけるので書いてみました。