Javaにおける抽象ファクトリパターン:オブジェクト生成をエレガントにマスターする
別名
- キット
抽象ファクトリデザインパターンの目的
Javaにおける抽象ファクトリパターンは、具体的なクラスを指定せずに、関連するオブジェクトまたは依存するオブジェクトのファミリーを作成するためのインターフェースを提供し、ソフトウェア設計におけるモジュール性と柔軟性を向上させます。
現実世界の例を用いた抽象ファクトリパターンの詳細な説明
現実世界の例
Javaで抽象ファクトリパターンを使用してさまざまなスタイルの家具(モダン、ビクトリア朝、素朴)を製造する家具会社を想像してください。各スタイルには、椅子、テーブル、ソファなどの製品が含まれています。各スタイルの一貫性を確保するために、会社は抽象ファクトリパターンを使用します。
このシナリオでは、抽象ファクトリは、関連する家具オブジェクト(椅子、テーブル、ソファ)のファミリーを作成するためのインターフェースです。各具体的なファクトリ(ModernFurnitureFactory、VictorianFurnitureFactory、RusticFurnitureFactory)は抽象ファクトリインターフェースを実装し、特定のスタイルに一致する製品セットを作成します。このようにして、クライアントは、インスタンス化の詳細を気にすることなく、モダンまたはビクトリア朝の家具のセット全体を作成できます。これにより、一貫したスタイルが維持され、あるスタイルの家具を別のスタイルに簡単に交換できます。
簡単に言うと
ファクトリのファクトリ。具体的なクラスを指定せずに、個々の関連する/依存するファクトリをグループ化するファクトリです。
Wikipediaによると
抽象ファクトリパターンは、具体的なクラスを指定せずに、共通のテーマを持つ個々のファクトリのグループをカプセル化する方法を提供します。
Javaにおける抽象ファクトリのプログラミング例
Javaの抽象ファクトリパターンを使用して王国を作成するには、共通のテーマを持つオブジェクトが必要です。エルフの王国にはエルフの王、エルフの城、エルフの軍隊が必要であり、オークの王国にはオークの王、オークの城、オークの軍隊が必要です。王国内のオブジェクト間には依存関係があります。
上記の王国の例を変換します。まず、王国内のオブジェクトのインターフェースと実装を用意します。
public interface Castle {
String getDescription();
}
public interface King {
String getDescription();
}
public interface Army {
String getDescription();
}
// Elven implementations ->
public class ElfCastle implements Castle {
static final String DESCRIPTION = "This is the elven castle!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class ElfKing implements King {
static final String DESCRIPTION = "This is the elven king!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
public class ElfArmy implements Army {
static final String DESCRIPTION = "This is the elven Army!";
@Override
public String getDescription() {
return DESCRIPTION;
}
}
// Orcish implementations similarly -> ...
次に、王国のファクトリの抽象化と実装を用意します。
public interface KingdomFactory {
Castle createCastle();
King createKing();
Army createArmy();
}
public class ElfKingdomFactory implements KingdomFactory {
@Override
public Castle createCastle() {
return new ElfCastle();
}
@Override
public King createKing() {
return new ElfKing();
}
@Override
public Army createArmy() {
return new ElfArmy();
}
}
// Orcish implementations similarly -> ...
これで、さまざまな王国のファクトリのためのファクトリを設計できます。この例では、`ElfKingdomFactory`または`OrcKingdomFactory`のインスタンスを返す役割を担う`FactoryMaker`を作成しました。クライアントは`FactoryMaker`を使用して、目的の具体的なファクトリを作成できます。そのファクトリは、今度は異なる具体的なオブジェクト(`Army`、`King`、`Castle`から派生)を生成します。この例では、クライアントが要求する王国のファクトリのタイプをパラメータ化する列挙型も使用しました。
public static class FactoryMaker {
public enum KingdomType {
ELF, ORC
}
public static KingdomFactory makeFactory(KingdomType type) {
return switch (type) {
case ELF -> new ElfKingdomFactory();
case ORC -> new OrcKingdomFactory();
};
}
}
これが、例となるアプリケーションのメイン関数です。
LOGGER.info("elf kingdom");
createKingdom(Kingdom.FactoryMaker.KingdomType.ELF);
LOGGER.info(kingdom.getArmy().getDescription());
LOGGER.info(kingdom.getCastle().getDescription());
LOGGER.info(kingdom.getKing().getDescription());
LOGGER.info("orc kingdom");
createKingdom(Kingdom.FactoryMaker.KingdomType.ORC);
LOGGER.info(kingdom.getArmy().getDescription());
LOGGER.info(kingdom.getCastle().getDescription());
LOGGER.info(kingdom.getKing().getDescription());
プログラム出力
07:35:46.340 [main] INFO com.iluwatar.abstractfactory.App -- elf kingdom
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven army!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven castle!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven king!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- orc kingdom
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc army!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc castle!
07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc king!
抽象ファクトリパターンのクラス図

Javaで抽象ファクトリパターンを使用する場合
Javaで抽象ファクトリパターンを使用する場合
- システムは、製品の作成、構成、表現方法から独立している必要があります。
- 複数の製品ファミリーのいずれかでシステムを構成する必要があります。
- 関連する製品オブジェクトのファミリーをまとめて使用し、一貫性を強制する必要があります。
- インターフェースのみを公開し、実装を公開しない製品のクラスライブラリを提供する必要があります。
- 依存関係のライフタイムは、コンシューマーのライフタイムよりも短くなければなりません。
- 依存関係は、実行時の値またはパラメータを使用して構築する必要があります。
- 実行時にファミリーから使用する製品を選択する必要があります。
- 新しい製品またはファミリーを追加しても、既存のコードを変更する必要はありません。
抽象ファクトリパターンのJavaチュートリアル
抽象ファクトリパターンのメリットとデメリット
メリット
柔軟性:コードを変更せずに製品ファミリーを簡単に切り替えることができます。
デカップリング:クライアントコードは抽象インターフェースのみとやり取りするため、移植性と保守性が向上します。
再利用性:抽象ファクトリと製品は、プロジェクト間でのコンポーネントの再利用を促進します。
保守性:個々の製品ファミリーへの変更は局所化されるため、更新が簡素化されます。
デメリット
複雑さ:抽象インターフェースと具体的なファクトリを定義することで、初期のオーバーヘッドが増加します。
間接性:クライアントコードはファクトリを介して間接的に製品とやり取りするため、透明性が低下する可能性があります。
Javaにおける抽象ファクトリパターンの現実世界のアプリケーション
- さまざまなルックアンドフィールオプションを提供するためのJava Swingの`LookAndFeel`クラス。
- さまざまなGUIコンポーネントを作成するためのJava Abstract Window Toolkit(AWT)のさまざまな実装。
- javax.xml.parsers.DocumentBuilderFactory
- javax.xml.transform.TransformerFactory
- javax.xml.xpath.XPathFactory
関連するJavaデザインパターン
- ファクトリメソッド:抽象ファクトリは、製品を作成するためにファクトリメソッドを使用します。
- シングルトン:抽象ファクトリクラスは、多くの場合、シングルトンとして実装されます。
- ファクトリキット:抽象ファクトリに似ていますが、柔軟な方法で関連するオブジェクトのセットの構成と管理に重点を置いています。