ゲームが作れるようになるまでがんばる日記

ゲーム制作のことを中心にゲームに関することを書いています

Factory Methodでコンストラクタを置き換える

インスタンスを作成するときはnew演算子でクラス名を指定する。つまり呼び出す側はそのクラス名を知っていなければならない。それを隠蔽するのがFactory Method。
たとえば、プレイヤーが魔法を使うような場合。魔法には低レベルと高レベルの2種類があり、プレイヤーのレベルによって変わるとする。

// 魔法の抽象クラス
public abstract class Magic {
    public abstract void use();
}
// 低レベル魔法
public class MagicLow extends Magic {
    @Override public void use() {
        System.out.println("Low Magic");
    }
}
// 高レベル魔法
public class MagicHigh extends Magic {
    @Override public void use() {
        System.out.println("High Magic");
    }
}
// テストメイン
public class Main {
    public static void main(String[] args) {
        int playerlevel = 1;
        Magic magic;

        if (playerlevel == 1) {
            magic = new MagicLow();
        } else {
            magic = new MagicHigh();
        }
        magic.use();
    }
}

このようにプレイヤー(この例ではMainクラス)が2種類の魔法のクラス名を知っていなければならない。そこでFactory Methodでコンストラクタを置き換える。

手順

Factory Methodを作る
中では今のコンストラクタを呼ぶ
Factory Methodで呼び出すように変更
コンストラクタの呼び出しをFactory Methodで呼び出す。

コンパイルしてテスト。

コンストラクタをprivateに変更する
こうすればコンストラクタを呼び出しているところが残っていた場合コンパイルでエラーになる。

コンパイルして確認。
リファクタリング後は次のとおり。

// 魔法の抽象クラス
public abstract class Magic {
    public abstract void use();
    public static Magic create(int level) {
        if (level == 1) {
            return new MagicLow();
        } else {
            return new MagicHigh();
        }
    }
}
// テストメイン
public class Main {
    public static void main(String[] args) {
        int playerlevel = 1;
        Magic magic = Magic.create(playerlevel);
        magic.use();
    }
}

Magicクラスにcreateメソッドを作成し、レベルに応じた魔法を作成して返すようにした。こうしてさらに魔法が増えてもMainクラスは変更せずに追加していくことができる。


参考文献:『Java言語で学ぶリファクタリング入門』