Javaにおけるファクトリーキットパターン:柔軟なコンポーネントアセンブリの作成
別名
- オブジェクトキット
- ツールキット
ファクトリーキットデザインパターンの意図
Javaにおけるファクトリーキットパターンは、分離されたビルダーとファクトリーインターフェースを持つファクトリーの作成を支援する強力なデザインパターンです。このパターンは、複雑なオブジェクト作成シナリオを管理するために不可欠です。
実際の例を用いたファクトリーキットパターンの詳細な解説
実際の例
ファクトリーキットパターンの現実世界の類似例は、さまざまな種類の料理が効率的に調理されるレストランの厨房です。この設定は、Javaでファクトリーキットパターンが動作する方法と同様に、柔軟性と一貫性を促進します。厨房には、さまざまな料理のために登録されたさまざまな材料とレシピがある中央ステーションがあると想像してください。注文が入ると、シェフはこの中央ステーションを参照して必要な材料を集め、登録されたレシピに従って料理を準備します。この設定により、厨房は各シェフがすべてのレシピの詳細を知る必要なしに、さまざまな料理の準備を効率的に管理および切り替えることができ、調理プロセスにおける柔軟性と一貫性が促進されます。
平易な言葉で言うと
ファクトリーキットは、設定可能なオブジェクトビルダーであり、ファクトリーを作成するためのファクトリーです。
Javaでのファクトリーキットパターンのプログラム例
ファクトリーキットパターンを使用して、望む武器を作成できるJavaの魔法の武器工場を想像してください。このパターンにより、設定可能なオブジェクトビルダーが可能になり、オブジェクトの種類が事前にわからないシナリオに最適です。
起動すると、マスターはそれを構成するために必要な武器のタイプの名前を唱えます。セットアップが完了すると、これらの武器のタイプは瞬時に召喚できます。
最初に、単純なWeapon
階層を定義しましょう。
public interface Weapon {
}
public enum WeaponType {
SWORD,
AXE,
BOW,
SPEAR
}
public class Sword implements Weapon {
@Override
public String toString() {
return "Sword";
}
}
// Axe, Bow, and Spear are defined similarly...
次に、ファクトリーに名前付きのビルダーを追加できる関数型インターフェースを定義します。
public interface Builder {
void add(WeaponType name, Supplier<Weapon> supplier);
}
例の核心は、ファクトリーキットパターンを効果的に実装するWeaponFactory
インターフェースです。メソッド#factory
は、構築するために必要なクラスを使用してファクトリーを構成するために使用されます。次に、メソッド#create
はオブジェクトインスタンスを作成するために使用されます。
public interface WeaponFactory {
static WeaponFactory factory(Consumer<Builder> consumer) {
var map = new HashMap<WeaponType, Supplier<Weapon>>();
consumer.accept(map::put);
return name -> map.get(name).get();
}
Weapon create(WeaponType name);
}
これで、WeaponFactory
がどのように使用できるかを示すことができます。
public static void main(String[] args) {
var factory = WeaponFactory.factory(builder -> {
builder.add(WeaponType.SWORD, Sword::new);
builder.add(WeaponType.AXE, Axe::new);
builder.add(WeaponType.SPEAR, Spear::new);
builder.add(WeaponType.BOW, Bow::new);
});
var list = new ArrayList<Weapon>();
list.add(factory.create(WeaponType.AXE));
list.add(factory.create(WeaponType.SPEAR));
list.add(factory.create(WeaponType.SWORD));
list.add(factory.create(WeaponType.BOW));
list.forEach(weapon -> LOGGER.info("{}", weapon.toString()));
}
例を実行したときのコンソール出力は次のとおりです。
06:32:23.026 [main] INFO com.iluwatar.factorykit.App -- Axe
06:32:23.029 [main] INFO com.iluwatar.factorykit.App -- Spear
06:32:23.029 [main] INFO com.iluwatar.factorykit.App -- Sword
06:32:23.029 [main] INFO com.iluwatar.factorykit.App -- Bow
Javaでファクトリーキットパターンを使用する場面
ファクトリーキットパターンを使用する場面
- ファクトリークラスが作成する必要があるオブジェクトのタイプを予測できず、カスタムビルダーの新しいインスタンスが必要な場合。
- グローバルなビルダーではなく、カスタムビルダーの新しいインスタンスが必要な場合。
- ファクトリーが構築できるオブジェクトのタイプをクラスの外で定義する必要がある場合。
- ビルダーとクリエーターのインターフェースを分離する必要がある場合。
- ゲーム開発や、ユーザーカスタマイズがあるその他のアプリケーション。
ファクトリーキットパターンのJavaチュートリアル
Javaでのファクトリーキットパターンの実際のアプリケーション
- ランタイム環境に基づいて異なるレンダリングエンジンがインスタンス化される可能性があるJava Development Kit(JDK)などのJavaライブラリ。
- 依存性注入が多用されるSpringのようなフレームワークやアプリケーションは、オブジェクトの作成をより柔軟に管理するために、このパターンを実装することがよくあります。
ファクトリーキットパターンの利点とトレードオフ
利点
- Javaのファクトリーキットパターンは、アプリケーション固有のクラスをコードにバインドする必要をなくすことで、疎結合を促進します。
- インスタンス化の責任をファクトリーオブジェクトに移すことでコードを簡素化し、開発プロセスをより効率的にします。
トレードオフ
- 追加のクラスとインターフェースを必要とすることで、コードに複雑さをもたらす可能性があります。
- 適切に管理しないと、依存関係の問題につながることがあります。
関連するJavaデザインパターン
- 抽象ファクトリー:関連するオブジェクトのファミリを作成するために、ファクトリーキットと組み合わせて使用されることがよくあります。
- ビルダー:同様のアプローチを使用して、複雑なオブジェクトを段階的に構築するために使用できます。
- プロトタイプ:プロトタイプインスタンスを複製することによって作成されるオブジェクトは、それを管理するためにファクトリーを使用することがよくあります。