デザインパターン入門(Abstract Factory)


この記事ではAbstract Factoryについてまとめます。
wikipediaによると「関連する一連のインスタンスを状況に応じて、適切に生成する方法を提供する。」とあります。
参考:デザインパターン(ソフトウェア)

以下の記事を参考にさせていただきました。
沈思黙考:デザインパターン(Abstract Factory パターン)
GoFのデザインパターンをJavaで実装して理解する Abstract Factory編

1つのクラスから他クラスのメソッドを利用する場合、staticクラスを除いて「new クラス名()」というインスタンス化が必要です。このデザインパターンでは呼び出し元クラスにnewしていたものを、Factoryというクラス群にインスタンス生成部分を移動して、Factoryクラスが保持するメソッド経由で利用したいクラスのインスタンスを取得します。

実装例

ガソリンスタンドでハイオクとレギュラーを給油するケースをAbstract Factoryで表現します。

NO ファイル名 クラス内容
1 AbstractFactory.java ガソリンを給油することを定義した抽象クラス
2 ConcreteHighFactory.java ハイオクを給油する具象クラス
3 ConcreteRegularFactory.java レギュラーを給油する具象クラス
4 AbstractRefueling.java 給油抽象クラス
5 ConcreteHighRefueling.java ハイオク給油具象クラス
6 ConcreteRegularRefueling.java レギュラー給油具象クラス
7 Main.java 実行するクラス

Java

AbstractFactory.java
public abstract AbstractFactory {
    abstract AbstractRefueling getAbstractRefueling();
}
ConcreteHighFactory.java
public class ConcreteHighFactory extends AbstractFactory {
    @Override
    public AbstractRefueling getAbstractRefueling();
        return new ConcreteHighRefueling();
    }
}
ConcreteRegularFactory.java
public class ConcreteRegularFactory extends AbstractFactory {
    @Override
    public AbstractRefueling getAbstractRefueling();
        return new ConcreteRegularRefueling();
    }
}
AbstractRefueling.java
public abstract class AbstractRefueling {
    abstract payment();
    abstract refueling();
}
ConcreteHighRefueling.java
public class ConcreteHighRefueling extends AbstractRefueling {
    @Override
    public payment() {};
    @Override
    public refueling() {};
}
ConcreteRegularRefueling.java
public class ConcreteRegularRefueling extends AbstractRefueling {
    @Override
    public payment() {};
    @Override
    public refueling() {};
}
Main.java
public class Main {
    public static void main(String... args) {
        Factory fa = exec("High");
        AbstractRefueling ab = fa.getAbstractRefueling();
    }
    private static Factory exec(String env) {
        if (env == "high") {
                return new ConcreteHighFactory();
        } else if (env == "regular") {
                return new ConcreteRegularFactory();
        }
    }
}

以上のように、Mainメソッド上でハイオクガソリンを入れることを想定して、ハイオクガソリンを給油するクラスを受け取っています。必要であれば、Main.java内のexecメソッドにあるConclete〜Factoryを書き換えることでFactoryクラスで定義した他の機能に差し替えることができます。また今回のケースではハイオク、レギュラーの2種類を実装しましたが、軽油など処理の種類を追加する必要が出た場合は、抽象化できているため単純にクラスを追加するのみで済み、既存のハイオクやレギュラーのクラスに影響が少ないと言えます。しかし、クラスの追加には柔軟に対応できますが部品を追加する場合(この例では給油メソッドに加えて窓拭きメソッドを追加するなど)、影響範囲が全てのFactoryクラスに広がります。

デザインパターン一覧