技術共有

デザインパターン ファクトリーパターン

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

ファクトリパターンはオブジェクト指向プログラミングでよく使われるデザインパターンに属します。創作パターン種の。ファクトリ パターンは主にオブジェクトを作成するために使用されますが、コード内で直接使用する場合とは異なります。newキーワードの作成は、共通のインターフェイスを通じてオブジェクトを作成するため、オブジェクト作成プロセスがクライアント コードの使用から分離されるという点で異なります。以下は、ファクトリー パターンの詳細な紹介です。

1.ファクトリーモデルの主な特長

  1. カプセル化されたオブジェクトの作成プロセス: オブジェクト作成プロセスをファクトリ クラスにカプセル化します。クライアントは、作成する必要があるオブジェクトのタイプを指定するだけで、オブジェクトの特定の作成の詳細を気にすることなく、ファクトリ クラスを通じて必要なオブジェクトを取得できます。
  2. カップリングを減らす: 抽象ファクトリと具象ファクトリを分離することにより、クライアントとオブジェクトの間の結合が軽減され、クライアント プログラムの拡張と保守が容易になります。
  3. プログラムのスケーラビリティの向上: 新しい製品を追加する必要がある場合は、対応する特定の製品クラスと対応するファクトリ クラスを追加するだけで済みます。元のコードを変更する必要はありません。オープンクローズ原則 (拡張用にオープン、クローズ用) に準拠しています。これにより、コードのスケーラビリティが向上します。
  4. メンテナンスとアップグレードが簡単注: ファクトリ メソッドはオブジェクトの作成プロセスを 1 つのクラスに集中させるため、オブジェクトの作成メソッドを変更する必要がある場合は、対応するファクトリ クラスを変更するだけでよく、クライアントには影響しません。
  5. コードの再利用: ファクトリ パターンはオブジェクト作成プロセスを抽象化し、コードの再利用を実現し、コードの柔軟性と再利用性を高めることができます。

2. ファクトリーモデルの分類

ファクトリ パターンは主に、単純なファクトリ パターン(静的ファクトリ パターン)、ファクトリ メソッド パターン、抽象ファクトリ パターンの 3 種類に分類されます。

1. 静的ファクトリーメソッド
  1. 渡されたさまざまなパラメーターに基づいてさまざまなクラスのインスタンスを返すファクトリ クラスを定義します。
  2. 通常、ファクトリ クラスには複数の静的メソッドが含まれており、各メソッドは特定の製品の作成に対応します。
  3. 利点: 実装が簡単で理解しやすい。
  4. 欠点: 新しい製品を追加する場合、ファクトリ クラスのソース コードを変更する必要があり、開始と終了の原則に違反します。

単純なファクトリ パターン クラス図

2. ファクトリーメソッドパターン(ファクトリーメソッド)
  1. オブジェクトを作成するためのインターフェイス (抽象ファクトリー) を定義し、ただし、どのクラスをインスタンス化するかはサブクラスに決定させます
  2. ファクトリ メソッドを使用すると、クラスのインスタンス化をサブクラスに延期できます。
  3. 利点: 優れた拡張性。新しい製品を追加する必要がある場合、対応する特定の製品カテゴリと特定の工場カテゴリのみを追加する必要があります。
  4. 欠点: 製品を追加するたびに、特定のクラスとオブジェクト実装ファクトリーを追加する必要があり、システム内のクラスの数が 2 倍になり、システムの複雑さが増加します。

ファクトリメソッドパターン

3. 抽象ファクトリーパターン(Abstract Factory)
  1. 具体的なクラスを指定せずに、一連の関連オブジェクトまたは相互依存オブジェクトを作成するためのインターフェイスを提供します。
  2. 抽象ファクトリ パターンは、複数のファクトリ メソッド パターンを組み合わせて使用​​すると見ることができます。
  3. 利点: 製品ファミリーはクラス内に制限できます。特定のファクトリーは、製品ファミリー内のすべての製品を作成できなければなりません。
  4. 短所: システムの抽象化と理解の困難さが増し、システム内のクラスの数が大幅に増加します。

抽象的な工場パターン

3. ファクトリモデルの適用シナリオ

ファクトリ パターンは、データベース接続、UI コントロール、ファイル処理、ロギング、ネットワーク通信、メッセージ キュー、データ構造、暗号化と復号化、メッセージ プッシュ、タスク スケジューリングなど、実際の開発で幅広い用途に使用できます。これらのシナリオでは、ファクトリ パターンを使用すると、オブジェクトの作成プロセスを使用プロセスから分離でき、システムの柔軟性と拡張性が向上します。

4.ファクトリーモデルの例

1. 簡単なファクトリーパターンの例

単純なファクトリ パターンでは、渡されたパラメータに基づいてさまざまな型のインスタンスを返すことができるファクトリ クラスを定義します。

以下は、Java で書かれた単純なファクトリ パターンの例です。円、長方形、正方形のインスタンスを生成できるシェイプ ファクトリを作成します。まず、形状インターフェイス (Shape) と、このインターフェイスを実装するいくつかの具象クラス (Circle、Rectangle、Square) を定義します。

  1. // 形状接口
  2. interface Shape {
  3. void draw();
  4. }
  5. // 圆形类
  6. class Circle implements Shape {
  7. @Override
  8. public void draw() {
  9. System.out.println("Inside Circle::draw() method.");
  10. }
  11. }
  12. // 矩形类
  13. class Rectangle implements Shape {
  14. @Override
  15. public void draw() {
  16. System.out.println("Inside Rectangle::draw() method.");
  17. }
  18. }
  19. // 正方形类
  20. class Square implements Shape {
  21. @Override
  22. public void draw() {
  23. System.out.println("Inside Square::draw() method.");
  24. }
  25. }

次に、静的メソッドを使用してシェイプ オブジェクトを生成するファクトリ クラス (ShapeFactory) を定義します。

  1. // 形状工厂类
  2. class ShapeFactory {
  3. // 使用 getShape 方法获取形状类型的对象
  4. public static Shape getShape(String shapeType){
  5. if(shapeType == null){
  6. return null;
  7. }
  8. if(shapeType.equalsIgnoreCase("CIRCLE")){
  9. return new Circle();
  10. } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
  11. return new Rectangle();
  12. } else if(shapeType.equalsIgnoreCase("SQUARE")){
  13. return new Square();
  14. }
  15. return null;
  16. }
  17. }

最後に、ファクトリ クラスを使用してシェイプ オブジェクトを取得し、そのオブジェクトを呼び出すことができます。draw方法。

  1. public class FactoryPatternDemo {
  2. public static void main(String[] args) {
  3. // 获取 Circle 的对象,并调用它的 draw 方法
  4. Shape shape1 = ShapeFactory.getShape("CIRCLE");
  5. shape1.draw();
  6. // 获取 Rectangle 的对象,并调用它的 draw 方法
  7. Shape shape2 = ShapeFactory.getShape("RECTANGLE");
  8. shape2.draw();
  9. // 获取 Square 的对象,并调用它的 draw 方法
  10. Shape shape3 = ShapeFactory.getShape("SQUARE");
  11. shape3.draw();
  12. }
  13. }

この例では、ShapeFactoryクラスは作成を担当しますShapeインターフェースのインスタンス。クライアント コードは、型情報 (文字列など) を渡すことでこれを行います。ShapeFactoryクラスの静的メソッドgetShape目的の形状のインスタンスを取得します。このようにして、クライアントは特定のクラスの実装から切り離され、開始および終了の原則に準拠します。つまり、クライアント コードを変更せずに新しいシェイプ クラスを拡張できます。ただし、単純なファクトリ パターンの大きな欠点は、システムを新しい製品ファミリ (形状に加えて色など) で拡張する必要がある場合、ファクトリ クラスを変更する必要があり、オープン パッケージの一部に違反することです。 -閉鎖原則。この場合、Factory Method パターンまたは Abstract Factory パターンの使用を検討してください。

2. ファクトリメソッドパターン例

例としてまだ形を残していますが、エンジニアリング手法を使用してそれを作成します。

まず形状インターフェイス (Product) を定義し、3 つの実装クラスを作成します。

  1. // 形状接口
  2. interface Shape {
  3. void draw();
  4. }
  5. // 圆形类
  6. class Circle implements Shape {
  7. @Override
  8. public void draw() {
  9. System.out.println("Inside Circle::draw() method.");
  10. }
  11. }
  12. // 矩形类
  13. class Rectangle implements Shape {
  14. @Override
  15. public void draw() {
  16. System.out.println("Inside Rectangle::draw() method.");
  17. }
  18. }
  19. // 正方形类
  20. class Square implements Shape {
  21. @Override
  22. public void draw() {
  23. System.out.println("Inside Square::draw() method.");
  24. }
  25. }

次に、作成者インターフェイス (Creator) と具体的な作成者 (Concrete Creator) を定義します。

  1. // 创建者接口
  2. interface ShapeFactory {
  3. Shape getShape(String shapeType);
  4. }
  5. // 具体创建者类
  6. class RectangleFactory implements ShapeFactory {
  7. @Override
  8. public Shape getShape(String shapeType) {
  9. if (shapeType == null) {
  10. return null;
  11. }
  12. if (shapeType.equalsIgnoreCase("RECTANGLE")) {
  13. return new Rectangle();
  14. }
  15. return null;
  16. }
  17. }
  18. class CircleFactory implements ShapeFactory {
  19. @Override
  20. public Shape getShape(String shapeType) {
  21. if (shapeType == null) {
  22. return null;
  23. }
  24. if (shapeType.equalsIgnoreCase("CIRCLE")) {
  25. return new Circle();
  26. }
  27. return null;
  28. }
  29. }
  30. class SquareFactory implements ShapeFactory {
  31. @Override
  32. public Shape getShape(String shapeType) {
  33. if (shapeType == null) {
  34. return null;
  35. }
  36. if (shapeType.equalsIgnoreCase("SQUARE")) {
  37. return new Square();
  38. }
  39. return null;
  40. }
  41. }

最後に、具象クリエーター クラスを使用してシェイプ オブジェクトを取得し、そのオブジェクトを呼び出します。draw方法:

  1. public class FactoryMethodPatternDemo {
  2. public static void main(String[] args) {
  3. ShapeFactory shapeFactory = new CircleFactory();
  4. // 获取 Circle 的对象,并调用它的 draw 方法
  5. Shape shape1 = shapeFactory.getShape("CIRCLE");
  6. shape1.draw();
  7. // 使用 RectangleFactory 来获取 Rectangle 的对象
  8. shapeFactory = new RectangleFactory();
  9. Shape shape2 = shapeFactory.getShape("RECTANGLE");
  10. shape2.draw();
  11. // 使用 SquareFactory 来获取 Square 的对象
  12. shapeFactory = new SquareFactory();
  13. Shape shape3 = shapeFactory.getShape("SQUARE");
  14. shape3.draw();
  15. }
  16. }

この例では、各形状クラスに対応するファクトリ クラスを作成します。 (ただし、実際のアプリケーションでは、通常、製品クラスごとに個別のファクトリ クラスを作成することを避けるために、構成ファイルまたはリフレクションを介して、より一般的なファクトリ クラス構造が存在します)。これは、Factory Method パターンの基本原則を示すのに役立ちます。つまり、どのクラスをインスタンス化するかをファクトリのサブクラスに決定させます。 。ただし、この例の単純なケースでは、Simple Factory パターンを使用するか、コードの重複を減らすために他の設計パターンを検討する方がよいかもしれません。

3. 抽象ファクトリーの例

この例では、携帯電話を例として、携帯電話に関連する製品 (画面、バッテリー、オペレーティング システムなど) を抽象化し、これらのインターフェイスを実装するための特定の製品クラスを作成します。次に、これらの製品を生成するための抽象ファクトリ インターフェイスと具体的なファクトリ クラスを定義できます。以下は、Abstract Factory パターンを使用して、携帯電話のさまざまなメーカーやモデルのコンポーネント (画面とバッテリー) を作成する方法を示す簡略化された例です。

まず、製品インターフェイスと特定の製品を定義します。

  1. // 屏幕接口
  2. interface Screen {
  3. void display();
  4. }
  5. // 高端屏幕的实现
  6. class HighEndScreen implements Screen {
  7. @Override
  8. public void display() {
  9. System.out.println("显示高清屏幕");
  10. }
  11. }
  12. // 低端屏幕的实现
  13. class LowEndScreen implements Screen {
  14. @Override
  15. public void display() {
  16. System.out.println("显示普通屏幕");
  17. }
  18. }
  19. // 电池接口
  20. interface Battery {
  21. void charge();
  22. }
  23. // 高效电池的实现
  24. class HighEfficiencyBattery implements Battery {
  25. @Override
  26. public void charge() {
  27. System.out.println("快速充电");
  28. }
  29. }
  30. // 标准电池的实现
  31. class StandardBattery implements Battery {
  32. @Override
  33. public void charge() {
  34. System.out.println("标准充电");
  35. }
  36. }

次に、抽象ファクトリ インターフェイスと具象ファクトリ クラスを定義します。

  1. // 手机组件工厂接口
  2. interface PhoneFactory {
  3. Screen createScreen();
  4. Battery createBattery();
  5. }
  6. // 高端手机工厂
  7. class HighEndPhoneFactory implements PhoneFactory {
  8. @Override
  9. public Screen createScreen() {
  10. return new HighEndScreen();
  11. }
  12. @Override
  13. public Battery createBattery() {
  14. return new HighEfficiencyBattery();
  15. }
  16. }
  17. // 低端手机工厂
  18. class LowEndPhoneFactory implements PhoneFactory {
  19. @Override
  20. public Screen createScreen() {
  21. return new LowEndScreen();
  22. }
  23. @Override
  24. public Battery createBattery() {
  25. return new StandardBattery();
  26. }
  27. }

最後に、抽象ファクトリを使用して具体的な製品オブジェクトを作成するクライアント コード:

  1. public class PhoneFactoryPatternDemo {
  2. public static void main(String[] args) {
  3. // 使用高端手机工厂
  4. PhoneFactory highEndFactory = new HighEndPhoneFactory();
  5. Screen highEndScreen = highEndFactory.createScreen();
  6. Battery highEndBattery = highEndFactory.createBattery();
  7. highEndScreen.display();
  8. highEndBattery.charge();
  9. // 使用低端手机工厂
  10. PhoneFactory lowEndFactory = new LowEndPhoneFactory();
  11. Screen lowEndScreen = lowEndFactory.createScreen();
  12. Battery lowEndBattery = lowEndFactory.createBattery();
  13. lowEndScreen.display();
  14. lowEndBattery.charge();
  15. }
  16. }

この例では、それぞれが特定のタイプの画面とバッテリーを生産できる 2 つの携帯電話工場 (ハイエンドとローエンド) を定義します。クライアント コードは、抽象ファクトリ インターフェイスを通じて特定のファクトリ クラスと対話し、それによって特定の製品クラスからの分離を実現します。 。このようにして、将来新しい電話タイプ(ミッドレンジ電話など)を追加する必要がある場合、既存のクライアント コードを変更せずに、新しい製品クラスと対応するファクトリ クラスを追加するだけで済みます。

5. まとめ

ファクトリーパターンは非常に便利なデザインパターンですが、オブジェクトの作成プロセスをカプセル化し、結合を削減し、プログラムの拡張性やメンテナンスの容易性などを向上させます。 、ソフトウェア開発で広く使用されています。ただし、いくつかの点もあります工場の責任が重くなる、システム拡張が難しいなどのデメリットがあります。 。したがって、実際のアプリケーションでは、特定のシナリオとニーズに基づいてトレードオフと選択を行う必要があります。

ファクトリ パターン (単純なファクトリ、ファクトリ メソッド、抽象ファクトリ) が役立つ場合は、忘れずに「いいね」を押して収集してください。