ファクトリ メソッド デザイン パターンは、 創造的なデザインパターン これは、スーパークラスでオブジェクトを作成するためのインターフェイスを提供し、サブクラスが作成されるオブジェクトのタイプを変更できるようにします。オブジェクト作成ロジックを別のメソッドにカプセル化し、作成者と作成されたオブジェクト間の疎結合を促進します。このパターンは、作成されるオブジェクトの正確なタイプが異なる場合や、実行時に決定する必要がある場合に特に便利で、オブジェクト作成の柔軟性と拡張性が可能になります。
目次
- ファクトリ メソッド デザイン パターンとは何ですか?
- ファクトリ メソッド デザイン パターンをいつ使用するか?
- ファクトリメソッド設計パターンのコンポーネント
- ファクトリメソッド設計パターンの例
- ファクトリ メソッド デザイン パターンの使用例
- ファクトリメソッド設計パターンの利点
- ファクトリメソッド設計パターンの欠点
ファクトリ メソッド デザイン パターンとは何ですか?
ファクトリ メソッド デザイン パターンは、ソフトウェア エンジニアリングで使用される創造的なデザイン パターンで、スーパークラスでオブジェクトを作成するためのインターフェイスを提供すると同時に、サブクラスが作成されるオブジェクトのタイプを変更できるようにします。オブジェクト作成ロジックを別のメソッドにカプセル化し、インスタンス化プロセスを抽象化し、作成者と作成されたオブジェクト間の疎結合を促進します。このパターンは、サブクラスがファクトリ メソッドの独自の実装を定義して特定の種類のオブジェクトを作成できるようにすることで、コードベースの柔軟性、拡張性、保守性を実現します。
カプセル化プログラム
ファクトリ メソッド デザイン パターンをいつ使用するか?
ファクトリ メソッド設計パターンを使用します。
- オブジェクトの作成をカプセル化したい場合: 複雑なオブジェクト作成プロセスがある場合、またはプロセスが条件に応じて異なる場合は、このロジックをファクトリ メソッドにカプセル化すると、クライアント コードが簡素化され、再利用性が向上します。
- クライアント コードを具体的なクラスから分離したい場合: ファクトリ メソッド パターンを使用すると、インターフェイスまたは抽象クラスを通じてオブジェクトを作成し、具体的なクラスの特定の実装の詳細をクライアント コードから抽象化できます。これにより疎結合が促進され、既存のクライアント コードに影響を与えることなくシステムの変更や拡張が容易になります。
- 複数の製品バリエーションをサポートする必要がある場合: アプリケーションで製品のさまざまなバリエーションを作成する必要がある場合、または新しいタイプの製品が将来導入される可能性がある場合、ファクトリ メソッド パターンは、製品タイプごとにファクトリ メソッドを定義することで、これらのバリエーションに柔軟に対応する方法を提供します。
- カスタマイズまたは構成をサポートしたい場合: ファクトリを使用して構成ロジックをカプセル化することができ、クライアントはファクトリ メソッドにパラメータまたは構成オプションを提供することで作成プロセスをカスタマイズできます。
ファクトリメソッド設計パターンのコンポーネント
1. クリエイター
これは、ファクトリ メソッドを宣言する抽象クラスまたはインターフェイスです。通常、クリエーターには、オブジェクトを作成するためのファクトリーとして機能するメソッドが含まれています。作成されたオブジェクトを操作する他のメソッドも含まれる場合があります。
2. コンクリートクリエイター
Concrete Creator クラスは、特定の種類のオブジェクトを作成するためのファクトリ メソッドを実装する Creator のサブクラスです。各コンクリート クリエーターは、特定の製品を作成する責任を負います。
3. 製品
これは、ファクトリ メソッドが作成するオブジェクトのインターフェイスまたは抽象クラスです。 Product は、ファクトリ メソッドが作成できるすべてのオブジェクトの共通インターフェイスを定義します。
デスクトップ.iniとは何ですか
4. コンクリート製品
具体的な Product クラスは、ファクトリ メソッドが作成する実際のオブジェクトです。各具体的な Product クラスは、Product インターフェイスを実装するか、Product 抽象クラスを拡張します。
ファクトリメソッド設計パターンの例
以下は、ファクトリ メソッド デザイン パターンを理解するための問題ステートメントです。
二輪車、三輪車、四輪車など、さまざまなタイプの車両の作成を処理する必要があるソフトウェア アプリケーションについて考えてみましょう。各タイプの車両には、独自の特性と動作があります。
1. ファクトリ メソッド デザイン パターンなし
ジャワ /*package whatever //do not write package name here */ import java.io.*; // Library classes abstract class Vehicle { public abstract void printVehicle(); } class TwoWheeler extends Vehicle { public void printVehicle() { System.out.println('I am two wheeler'); } } class FourWheeler extends Vehicle { public void printVehicle() { System.out.println('I am four wheeler'); } } // Client (or user) class class Client { private Vehicle pVehicle; public Client(int type) { if (type == 1) { pVehicle = new TwoWheeler(); } else if (type == 2) { pVehicle = new FourWheeler(); } else { pVehicle = null; } } public void cleanup() { if (pVehicle != null) { pVehicle = null; } } public Vehicle getVehicle() { return pVehicle; } } // Driver program public class GFG { public static void main(String[] args) { Client pClient = new Client(1); Vehicle pVehicle = pClient.getVehicle(); if (pVehicle != null) { pVehicle.printVehicle(); } pClient.cleanup(); } }> 出力 I am two wheeler>
上記の設計にはどのような問題があるのでしょうか?
上記のコード設計では次のようになります。
- 密結合: クライアントクラス
Client>具体的なクラスを直接インスタンス化します (TwoWheeler>そしてFourWheeler>) 構築中に提供された入力タイプに基づきます。これにより、クライアントと具体的なクラスの間の結合が密になり、コードの保守と拡張が困難になります。 - 単一責任原則 (SRP) の違反: の
Client>このクラスは、入力タイプに基づいてインスタンス化する車両のタイプを決定するだけでなく、車両オブジェクトのライフサイクルの管理 (クリーンアップなど) も担当します。これは、クラスが変更する理由は 1 つだけであるべきであるという単一責任の原則に違反します。 - 限られたスケーラビリティ: 新しいタイプの車両を追加するには、
Client>オープンクローズの原則に違反するクラスです。この設計は、既存のコードを変更しないと新しいタイプの車両に対応できないため、拡張性がありません。
どうすれば問題を回避できるでしょうか?
- ファクトリ インターフェイスを定義します。 を作成します
VehicleFactory>車両を作成するためのメソッドを備えたインターフェイスまたは抽象クラス。 - コンクリートファクトリーの実装: 具象ファクトリ クラスを実装する (
TwoWheelerFactory>そしてFourWheelerFactory>) を実装するVehicleFactory>インターフェイスを提供し、特定の種類の車両のインスタンスを作成するメソッドを提供します。 - クライアントのリファクタリング: を変更します。
Client>を受け入れるクラスVehicleFactory>車両を直接インスタンス化するのではなく、インスタンスを作成します。クライアントは工場に車両を要求するため、車両タイプに基づく条件付きロジックが不要になります。 - 柔軟性の向上: このアプローチを使用すると、既存のクライアント コードを変更せずに、新しい車両タイプ用の新しいファクトリ クラスを作成するだけで、新しいタイプの車両を追加できます。
2. ファクトリーメソッドデザインパターンあり
コードをコンポーネントごとに分解してみましょう。

1. 製品インターフェース
ジャワ // Product interface representing a vehicle public abstract class Vehicle { public abstract void printVehicle(); }> 2. コンクリート製品
ジャワ // Concrete product classes representing different types of vehicles public class TwoWheeler extends Vehicle { public void printVehicle() { System.out.println('I am two wheeler'); } } public class FourWheeler extends Vehicle { public void printVehicle() { System.out.println('I am four wheeler'); } }> 3. クリエーターインターフェース(ファクトリーインターフェース)
ジャワ // Factory interface defining the factory method public interface VehicleFactory { Vehicle createVehicle(); }> 4. コンクリートクリエイター(コンクリート工場)
ジャワ // Concrete factory class for TwoWheeler public class TwoWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new TwoWheeler(); } } // Concrete factory class for FourWheeler public class FourWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new FourWheeler(); } }> この例の完全なコード:
ジャワ // Library classes abstract class Vehicle { public abstract void printVehicle(); } class TwoWheeler extends Vehicle { public void printVehicle() { System.out.println('I am two wheeler'); } } class FourWheeler extends Vehicle { public void printVehicle() { System.out.println('I am four wheeler'); } } // Factory Interface interface VehicleFactory { Vehicle createVehicle(); } // Concrete Factory for TwoWheeler class TwoWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new TwoWheeler(); } } // Concrete Factory for FourWheeler class FourWheelerFactory implements VehicleFactory { public Vehicle createVehicle() { return new FourWheeler(); } } // Client class class Client { private Vehicle pVehicle; public Client(VehicleFactory factory) { pVehicle = factory.createVehicle(); } public Vehicle getVehicle() { return pVehicle; } } // Driver program public class GFG { public static void main(String[] args) { VehicleFactory twoWheelerFactory = new TwoWheelerFactory(); Client twoWheelerClient = new Client(twoWheelerFactory); Vehicle twoWheeler = twoWheelerClient.getVehicle(); twoWheeler.printVehicle(); VehicleFactory fourWheelerFactory = new FourWheelerFactory(); Client fourWheelerClient = new Client(fourWheelerFactory); Vehicle fourWheeler = fourWheelerClient.getVehicle(); fourWheeler.printVehicle(); } }> 出力 I am two wheeler I am four wheeler>
上記のコードでは次のようになります。
アップキャスト
-
Vehicle>Product インターフェイスとして機能し、共通メソッドを定義しますprintVehicle()>すべてのコンクリート製品が実装する必要があります。 -
TwoWheeler>そしてFourWheeler>さまざまなタイプの車両を表す具体的な製品クラスであり、printVehicle()>方法。 -
VehicleFactory>メソッドを備えた Creator インターフェイス (Factory インターフェイス) として機能します。createVehicle()>ファクトリメソッドを表します。 -
TwoWheelerFactory>そしてFourWheelerFactory>を実装する具体的な作成者クラス (具体的なファクトリ) です。VehicleFactory>特定のタイプの車両のインスタンスを作成するためのインターフェイス。
ファクトリ メソッド デザイン パターンの使用例
ファクトリ メソッド デザイン パターンの一般的なアプリケーションをいくつか示します。
- 創作フレームワーク:
- JDBC (Java Database Connectivity) は、接続、ステートメント、結果セットの作成にファクトリを広範囲に使用します。 Spring や Guice などの依存性注入フレームワークは、Bean の作成と管理をファクトリに大きく依存しています。
- GUI ツールキット:
- Swing と JavaFX はファクトリーを使用してボタン、テキストフィールド、ラベルなどの UI コンポーネントを作成し、UI デザインのカスタマイズと柔軟性を可能にします。
- ロギングフレームワーク:
- Log4j や Logback などのロギング フレームワークは、ファクトリを使用してさまざまな構成のロガーを作成し、ロギング レベルと出力先の制御を可能にします。
- シリアル化と逆シリアル化:
- オブジェクト シリアル化フレームワークは、多くの場合、ファクトリを使用してシリアル化されたデータからオブジェクトを作成し、さまざまなシリアル化形式とバージョン管理をサポートします。
- プラグイン システム:
- プラグインベースのシステムは多くの場合、ファクトリを使用してプラグイン インスタンスを動的にロードおよび作成し、拡張性とカスタマイズを可能にします。
- ゲーム開発:
- ゲーム エンジンは多くの場合、ファクトリを使用してさまざまな種類のゲーム オブジェクト、キャラクター、レベルを作成し、コードの編成と柔軟性を促進します。
- ウェブ開発:
- Web フレームワークは、ファクトリを使用してビュー コンポーネント、コントローラー、サービスを作成する場合があり、Web アプリケーションのモジュール性とテスト容易性を実現します。
ファクトリメソッド設計パターンの利点
ファクトリ メソッド デザイン パターンの利点は次のとおりです。
25 c から k
- デカップリング: これにより、オブジェクト作成ロジックが、それらのオブジェクトを使用するクライアント コードから分離されます。これにより、作成プロセスを変更してもクライアント コードを変更する必要がなくなるため、コードの柔軟性と保守性が向上します。
- 拡張性: クライアント コードを変更せずに、新しい種類の製品を導入するのは簡単です。新しい Concrete Creator サブクラスを作成し、ファクトリ メソッドを実装して新しい製品を生成するだけです。
- テスト容易性: テスト中に製品作成をモックまたはスタブアウトできるため、単体テストが簡素化されます。実際のオブジェクトの作成に依存せずに、さまざまな製品実装を個別にテストできます。
- コードの再利用性: ファクトリ メソッドは、オブジェクトの作成が必要なアプリケーションのさまざまな部分で再利用できます。これにより、オブジェクト作成ロジックの一元化と再利用が促進されます。
- カプセル化: これにより、具体的な製品クラスがクライアント コードから隠蔽され、コードが特定の実装に依存することが少なくなります。これにより、メンテナンス性が向上し、カップリングが軽減されます。
ファクトリメソッド設計パターンの欠点
ファクトリ メソッド デザイン パターンの欠点は次のとおりです。
- 複雑さの増加: 追加のクラスとインターフェイスが導入され、抽象化の層が追加されるため、特にパターンに慣れていない人にとって、コードの理解と保守がより複雑になります。
- オーバーヘッド: 多態性と動的バインディングの使用はパフォーマンスにわずかに影響を与える可能性がありますが、ほとんどのアプリケーションでは無視できる程度です。
- 製品階層内の緊密な結合: Concrete Creator は依然として、対応する Concrete 製品と密接に結合しています。一方を変更すると、もう一方も変更する必要が生じることがよくあります。
- 具体的なサブクラスへの依存関係: クライアント コードは依然として抽象 Creator クラスに依存しているため、ファクトリ メソッドを正しく呼び出すにはその具体的なサブクラスの知識が必要です。
- 過剰使用の可能性: アプリケーションのオーバーエンジニアリングを避けるために、ファクトリー メソッド パターンを慎重に使用することが重要です。単純なオブジェクトの作成は、多くの場合、ファクトリを必要とせずに直接処理できます。
- テストの課題: ファクトリ ロジック自体のテストは、より複雑になる場合があります。