web-dev-qa-db-ja.com

デザインパターン:ファクトリーvsファクトリーメソッドvs抽象ファクトリー

ウェブサイトからデザインパターンを読んでいた

そこで、Factory、Factory method、Abstract factoryについて読みましたが、それらは非常に紛らわしいので、定義が明確ではありません。定義によると

ファクトリ-インスタンス化ロジックをクライアントに公開せずにオブジェクトを作成し、共通のインターフェースを介して新しく作成されたオブジェクトを参照します。 ファクトリーメソッドの簡易バージョン

ファクトリメソッド-オブジェクトを作成するためのインターフェイスを定義しますが、サブクラスにインスタンス化するクラスを決定させ、共通インターフェイスを介して新しく作成されたオブジェクトを参照させます。

Abstract Factory-クラスを明示的に指定せずに、関連するオブジェクトのファミリーを作成するためのインターフェースを提供します。

また、Abstract Factory対Factory Methodに関して他のstackoverflowスレッドを見ましたが、そこに描かれたUMLダイアグラムは私の理解をさらに悪化させます。

誰でも教えてもらえますか

  1. これら3つのパターンはどのように互いに異なっていますか?
  2. どちらを使用するか?
  3. また、可能であれば、これらのパターンに関連するJavaの例はありますか?
156

3つのFactoryタイプはすべて同じことを行います。これらは「スマートコンストラクター」です。

2種類のフルーツを作成できるようにしたいとしましょう:Appleとオレンジ。

工場

Factoryは「固定」されており、サブクラス化のない1つの実装しかありません。この場合、次のようなクラスがあります。

class FruitFactory {

  public Apple makeApple() {
    // Code for creating an Apple here.
  }

  public Orange makeOrange() {
    // Code for creating an orange here.
  }

}

使用例:AppleまたはOrangeの構築は、どちらかをコンストラクターで処理するには少し複雑すぎます。

工場工法

通常、ファクトリメソッドは、クラス内でいくつかの一般的な処理を行うが、実際に使用するフルーツの種類を変更する場合に使用されます。そう:

abstract class FruitPicker {

  protected abstract Fruit makeFruit();

  public void pickFruit() {
    private final Fruit f = makeFruit(); // The fruit we will work on..
    <bla bla bla>
  }
}

...次に、サブクラスでファクトリメソッドを実装することにより、FruitPicker.pickFruit()の共通機能を再利用できます。

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}

抽象工場

通常、抽象ファクトリは、「同じ種類」である必要があり、いくつかの共通の基本クラスを持つ必要があるオブジェクトのファミリ全体を作成できるようにする場合の、依存性注入/戦略などに使用されます。漠然と果物に関連する例を次に示します。ここでの使用例は、AppleでOrangePickerを誤って使用しないようにすることです。同じ工場からフルーツとピッカーを入手する限り、それらは一致します。

interface PlantFactory {

  Plant makePlant();

  Picker makePicker(); 

}

public class AppleFactory implements PlantFactory {
  Plant makePlant() {
    return new Apple();
  }

  Picker makePicker() {
    return new ApplePicker();
  }
}

public class OrangeFactory implements PlantFactory {
  Plant makePlant() {
    return new Orange();
  }

  Picker makePicker() {
    return new OrangePicker();
  }
}
212
Anders Johansen
  1. これら3つのパターンはどのように互いに異なっていますか?

Factory:インスタンス化ロジックをクライアントに公開せずにオブジェクトを作成します。

Factory Method:オブジェクトを作成するためのインターフェースを定義しますが、サブクラスにインスタンス化するクラスを決定させます。 Factoryメソッドにより、クラスはインスタンス化をサブクラスに延期できます。

Abstract Factory:具象クラスを指定せずに関連オブジェクトまたは依存オブジェクトのファミリーを作成するためのインターフェースを提供します。

AbstractFactoryパターンは構成を使用してオブジェクトを作成する責任を別のクラスに委任しますが、Factoryメソッド設計パターンは継承を使用し、派生クラスに依存しますオブジェクトを作成するサブクラス

  1. どちらを使用するか?

Factory:クライアントはクラスを必要とするだけで、取得する具体的な実装を気にしません。

Factory Method:クライアントは、実行時に作成する必要のある具体的なクラスを知りませんが、ジョブを実行するクラスを取得したいだけです。 。

AbstactFactory:システムで複数の製品ファミリを作成する必要がある場合、または実装の詳細を公開せずに製品のライブラリを提供する場合。

多くの場合、抽象ファクトリクラスはファクトリメソッドで実装されます。ファクトリメソッドは通常、テンプレートメソッド内で呼び出されます。

  1. また、可能であれば、これらのパターンに関連するJavaの例はありますか?

FactoryおよびFactoryMethod

意図:

オブジェクトを作成するためのインターフェースを定義しますが、インスタンス化するクラスをサブクラスに決定させます。ファクトリメソッドを使用すると、クラスはインスタンス化をサブクラスに延期できます。

ML図

enter image description here

Product:Factoryメソッドが作成するオブジェクトのインターフェースを定義します。

ConcreteProduct:製品インターフェイスの実装

Creator:Factoryメソッドを宣言します

ConcreateCreator:Factoryメソッドを実装して、ConcreteProductのインスタンスを返す

問題ステートメント:ゲームインターフェイスを定義するファクトリメソッドを使用して、ゲームのファクトリを作成します。

コードスニペット:

ファクトリパターン。いつファクトリメソッドを使用するか

他の創造パターンとの比較:

  1. Factory Methodを使用して設計を開始し(複雑さを軽減し、よりカスタマイズ可能なサブクラスを増殖)、Abstract Factory、Prototype 、またはBuilder(より柔軟で複雑)

  2. Abstract Factoryクラスは多くの場合Factory Methodsで実装されますが、 プロトタイプを使用して実装する

さらに読むための参照: Sourcemaking design-patterns

22
Ravindra babu

Factory-複雑なオブジェクトを作成するためにファクトリクラスを分離します。

例:Fruitのオブジェクトを作成するFruitFactoryクラス

class FruitFactory{

public static Fruit getFruit(){...}

}

Factory Method-ファクトリーの個別のクラス全体ではなく、そのクラス自体に1つのメソッドをファクトリーとして追加するだけです。

例:

Calendar.getInstance() (Java's Calendar)

工場の抽象的な方法-工場の工場

例:コンピューター部品の工場を建設したいとしましょう。そのため、ラップトップ、デスクトップ、サーバーなどのコンピューターにはいくつかの種類があります。

そのため、各コンピュータータイプにはファクトリーが必要です。だから私たちは以下のような工場の1つの高レベルの工場を作成します

ComputerTypeAbstractFactory.getComputerPartFactory(String computerType) ---> This will return PartFactory which can be one of these ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

現在、これら3つ自体が再び工場になっています。 (PartFactory自体を処理しますが、内部では、抽象ファクトリで提供したものに基づいて個別の実装があります)

  Interface-> PartFactory. getComputerPart(String s), 
Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)

編集:コメントの異議に従って、Abstract Factoryの正確なインターフェイスを提供するように編集されました。

17
Ravi K

すべての設計パターンは、書かれた、動作中のコードが触れられないことを保証するのに役立ちます。作業コードに触れると、既存の作業フローに欠陥があり、何も壊さないことを確認するために、さらに多くのテストを行う必要があることは誰もが知っています。

ファクトリパターンは、入力基準に基づいてオブジェクトを作成するため、このようなオブジェクトを作成するか、このオブジェクトを作成するようなコードを記述する必要はありません。これの良い例は旅行ウェブサイトです。旅行Webサイトは、旅行(フライト、電車、バス)のみを提供するか、ホテルを提供するか、観光スポットパッケージを提供します。ここで、ユーザーが次に選択するとき、Webサイトは作成する必要のあるオブジェクトを決定する必要があります。旅行またはホテルのオブジェクトのみを作成する必要があります。

ポートフォリオに別のWebサイトを追加することを想定している場合、たとえば、現在はタクシーを検索してオンラインで支払いを行うカープーリングWebサイトなど、同じコアを使用すると考えている場合は、コアで抽象ファクトリーを使用できます。この方法で、タクシーとカープールのもう1つの工場にスナップインできます。

両方の工場は互いに関係がないため、異なる工場に保管するのに適した設計です。

これが今明確であることを願っています。この例を念頭に置いてWebサイトをもう一度調べてください。うまくいけばうまくいきます。そして、パターンを正しく表現できたことを本当に願っています:)。

10
Siddharth

この答えについては、「Gang of Four」の本を参照してください。

本にはno "Factory"、 "Simple Factory"、 "Virtual Factory"の定義があります。 通常人々が「ファクトリ」パターンについて話しているとき、彼らは話しているかもしれませんクラスの特定のオブジェクトを作成するもの(しかし、「ビルダー」パターンではありません);それらは多かれ少なかれ「Factory Method」または「Abstract Factory」パターンを参照します。正式な用語ではないため、誰もが「ファクトリ」を実装できません(一部の人々\会社\コミュニティは独自の語彙を持つことができることに留意してください)。

onlyには、「Abstract Factory」と「Factory Method」の定義が含まれています。

本からの定義と、両方が非常に混乱しやすい理由の簡単な説明を以下に示します。他の答えで見つけることができるので、コード例を省略します。

Factory Method(GOF):オブジェクトを作成するためのインターフェースを定義しますが、サブクラスにインスタンス化するクラスを決定させます。ファクトリメソッドを使用すると、クラスはインスタンス化をサブクラスに延期できます。

Abstract Factory(GOF):具象クラスを指定せずに関連オブジェクトまたは依存オブジェクトのファミリーを作成するためのインターフェースを提供します。

混乱の原因:多くの場合、「Factory Method」パターンで使用されるクラスを「Factory」として呼び出すことができます。このクラスは、定義により抽象的です。そのため、このクラスを「抽象ファクトリ」と呼ぶのは簡単です。しかし、それはクラスの名前です。 「Abstract Factory」パターン(クラス名!=パターン名)と混同しないでください。 「Abstract Factory」パターンは異なります-それはnot抽象クラスを使用します。互いに関連する、または特定の方法で作成する必要がある、より大きなオブジェクトの一部を作成するためのインターフェイス(必ずしもプログラミング言語インターフェイスではない)を定義します。

1
Pavel Sapehin
AbstractProductA, A1 and A2 both implementing the AbstractProductA
AbstractProductB, B1 and B2 both implementing the AbstractProductB

interface Factory {
    AbstractProductA getProductA(); //Factory Method - generate A1/A2
}

Factory Methodを使用すると、AbstractProductAのA1またはA2を作成できます。

interface AbstractFactory {
    AbstractProductA getProductA(); //Factory Method
    AbstractProductB getProductB(); //Factory Method
}

しかし、Abstract Factoryは複数のファクトリメソッド(例:2つのファクトリメソッド)を持ち、それらのファクトリメソッドを使用して、オブジェクト/関連オブジェクトのセットを作成します。ユーザーは、Abstract Factoryを使用して、AbstractProductA、AbstractProductBのA1、B1オブジェクトを作成できます。

1
rameshvanka