web-dev-qa-db-ja.com

Abstract FactoryとFactoryのデザインパターンの違いは何ですか?

これら2つのパターンの違いについての投稿はたくさんありますが、見つけられないことがいくつかあります。

私が読んできたことから、ファクトリメソッドパターンは単一の具体的な製品を作成する方法を定義することを可能にしますが、彼らは一般的な製品を見るのでクライアントから実装を隠します。私の最初の質問は抽象ファクトリーについてです。その役割は、1つの具象オブジェクトではなく、具体的なオブジェクトのファミリを作成することを許可することです(使用する特定のファクトリによって異なります)。抽象ファクトリは、どのメソッドを呼び出すかに応じて、1つの非常に大きなオブジェクトまたは多くのオブジェクトのみを返しますか?

私の最後の2つの質問は、私が多くの場所で見たことを完全には理解できない一重引用符についてのものです。

両者の1つの違いは、抽象ファクトリパターンでは、クラスがコンポジションを介してオブジェクトのインスタンス化の責任を別のオブジェクトに委任するのに対し、ファクトリメソッドパターンは継承を使用し、サブクラスに依存して目的のオブジェクトのインスタンス化を処理することです。

私の理解するところでは、ファクトリメソッドパターンには、ConcreteCreatorがどのConcreteProductをインスタンス化するかを知る責任を負うようにするCreatorインターフェースがあります。これは、オブジェクトのインスタンス化を処理するために継承を使用することによって何を意味するのでしょうか。

さて、その引用に関して、Abstract Factoryパターンはどのように厳密にオブジェクトインスタンス化の責任を他のオブジェクトにコンポジションを通して委譲するのでしょうか。これは何を意味するのでしょうか? Abstract Factoryパターンでも継承プロセスを使用して構築プロセスを実行しているように見えますが、それでもやはりこれらのパターンについて学習しています。

特に最後の質問に関しての手助けは大歓迎です。

387
Silverbolt

両者の違い

「ファクトリメソッド」と「抽象ファクトリ」の主な違いは、ファクトリメソッドは単一のメソッドであり、抽象ファクトリはオブジェクトであるということです。私は多くの人がこれら二つの用語を混同して、それらを同じ意味で使い始めていると思います。私がそれらを学んだときに何が違うのかを正確に見つけるのに苦労したことを覚えています。

ファクトリメソッドは単なるメソッドであるため、サブクラスでオーバーライドすることができます。したがって、引用の後半になります。

... Factory Methodパターンは継承を使用し、目的のオブジェクトのインスタンス化を処理するためにサブクラスに依存します。

引用は、オブジェクトがそれ自身のfactoryメソッドを呼び出していると仮定しています。したがって、戻り値を変更できる唯一のものはサブクラスです。

抽象ファクトリは、複数のファクトリメソッドを持つオブジェクトです。あなたの引用の前半を見てください。

Abstract Factoryパターンでは、クラスはオブジェクトのインスタンス化の責任を他のオブジェクトにコンポジションを通じて委任します。

彼らが言っているのは、Fooオブジェクトを作りたいオブジェクトAがあるということです。 Fooオブジェクト自体を(たとえばファクトリメソッドで)作成する代わりに、Fooオブジェクトを作成するためにdifferentオブジェクト(抽象ファクトリ)を取得します。

コード例

あなたに違いを見せるために、これは使用中のファクトリーメソッドです:

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

そして、これが使用中の抽象的なファクトリーです。

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here
421
Tom Dalling

Abstract factoryは生成されるべきオブジェクトのメソッドを定義する抽象メソッドで基本クラスを作成します。基本クラスを派生する各ファクトリクラスは、各オブジェクトタイプの独自の実装を作成できます。

enter image description here

ファクトリメソッドは、クラス内にオブジェクトを作成するための単純なメソッドです。通常集約ルートに追加されます(OrderクラスにはCreateOrderLineというメソッドがあります)

enter image description here

抽象的な工場

以下の例では、メッセージングシステムからキューの作成を切り離し、コードベースを変更することなくさまざまなキューシステムの実装を作成できるようにインターフェイスを設計します。

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

ファクトリーメソッド

HTTPサーバの問題は、リクエストごとに常にレスポンスが必要なことです。

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

ファクトリメソッドがなければ、HTTPサーバユーザ(つまりプログラマ)はIHttpRequestインタフェースの目的に反する実装固有のクラスを使わざるをえなくなるでしょう。

したがって、レスポンスクラスの作成も抽象化されるようにファクトリメソッドを導入します。

概要

違いは、ファクトリメソッドオブジェクトを作成することはできません _を含むクラスの意図した目的 _は、オブジェクトを作成するためにのみ使用する必要があるということです。

オブジェクトを作成するときにLSP( Liskov Substitution principle )を破るのは簡単なので、ファクトリメソッドを使用するときは注意が必要です。

112
jgauffin

AbstractFactoryとFactoryの設計パターンの違いは次のとおりです。

  • ファクトリメソッドは1つの製品のみを作成するために使用されますが、抽象ファクトリは関連または従属製品のファミリを作成することについてです。
  • Factory Methodパターンはオブジェクトを作成するためのメソッドをクライアントに公開しますが、Abstract Factoryの場合は関連オブジェクトのファミリーを公開しますこれらは、これらのFactoryメソッドで構成されています。
  • ファクトリメソッドパターンは単一オブジェクトの構築を隠しますが、as抽象ファクトリメソッドは関連オブジェクトのファミリの構築を隠します。抽象ファクトリは通常(一連の)ファクトリメソッドを使って実装されます。
  • AbstractFactoryパターンはコンポジションを使用してオブジェクトを作成する責任を別のクラスに委任します。Factoryデザインパターンは継承を使用し、派生クラスまたは派生クラスに依存しますオブジェクトを作成するクラス.
  • ファクトリメソッドパターンの背後にある考え方は、実行時にどの具体的なクラスを作成する必要があるのか​​クライアントにはわからないが、取得したいという場合に対応できるということです。 whileAbstractFactoryパターンを実行するクラスは、システムが複数の製品ファミリを作成する必要がある場合、または実装の詳細を公開せずに製品のライブラリを提供する場合に最適です。 !

ファクトリメソッドパターンの実装: Factory Method UML

AbstractFactoryパターンの実装:

Abstract Factory UML

87

Abstract Factoryは関連製品を作成するためのインターフェースですが、Factory Methodは1つのメソッドに過ぎません。抽象ファクトリは複数のファクトリメソッドで実装できます。

Abstract Factory UML

22
Trying

Abstract FactoryとFactory Methodの主な違いは、Abstract FactoryはCompositionによって実装されることです。しかし、ファクトリメソッドは継承によって実装されています。

はい、あなたはそれを正しく読んでいます:これら二つのパターンの主な違いは古い 構成対継承 の議論です。

UMLダイアグラムは(GoF)の本にあります。このスレッドの上位2つの回答の例を組み合わせると、どちらの回答よりも優れたデモンストレーションが得られると思いますので、コード例を示したいと思います。さらに、クラス名とメソッド名に本の用語を使用しました。

抽象ファクトリ

  1. ここで最も重要な点は、抽象ファクトリはクライアントに注入されたであるということです。これが、我々がAbstract FactoryがCompositionによって実装されていると言う理由です。多くの場合、依存性注入フレームワークがそのタスクを実行します。しかし、フレームワークはDIには必要ありません。
  2. 2つ目の重要な点は、ここでの具体的な工場はファクトリメソッドの実装ではないということです。ファクトリメソッドのコード例は、以下にさらに示されています。
  3. そして最後に、3つ目の注意点は、製品間の関係です。この場合、発信キューと返信キューです。 1つのコンクリート工場がAzureキューを、もう1つのMSMQを製造します。 GoFはこの製品の関係を「ファミリー」と呼び、この場合のファミリーはクラス階層を意味しないことに注意することが重要です。
public class Client {
    private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }

    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }

    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }
}

public interface AbstractFactory_MessageQueue {
    OutboundQueue createProductA();
    ReplyQueue createProductB();
}

public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new AzureMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }
}

public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new MsmqMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }
}

ファクトリメソッド

  1. ここで最も重要な点は、ConcreteCreatorクライアントです。つまり、クライアントはその親がfactoryMethod()を定義するサブクラスです。これが、Factory MethodがInheritanceによって実装されていると言う理由です。
  2. 2つ目の重要な点は、ファクトリメソッドパターンがテンプレートメソッドパターンの特殊化に他ならないことを覚えておくことです。 2つのパターンは同じ構造を共有しています。目的が異なるだけです。ファクトリメソッドは創造的(何かを構築する)であり、テンプレートメソッドは振る舞い(それは何かを計算する)です。
  3. そして最後に、3つ目の注意点は、Creator(parent)クラスが独自のfactoryMethod()を呼び出すことです。親クラスからanOperation()を削除し、単一のメソッドのみを残した場合、それはもはやFactory Methodパターンではありません。つまり、Factoryメソッドは、親クラスの2つより少ないメソッドで実装することはできません。そして一方が他方を呼び出さなければなりません。
public abstract class Creator {
    public void anOperation() {
        Product p = factoryMethod();
        p.whatever();
    }

    protected abstract Product factoryMethod();
}

public class ConcreteCreator extends Creator {
    @Override
    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}

その他&雑貨工場のパターン

GoFは2つの異なるFactoryパターンを定義していますが、これらが存在する唯一のFactoryパターンではありません。それらは必ずしも最も一般的に使用されるファクトリパターンでさえありません。有名な3番目の例は、Effective JavaのJosh BlochのStatic Factory Patternです。 Head First Design Patternsの本には、Simple Factoryと呼ばれるさらに別のパターンが含まれています。

すべてのFactoryパターンがGoFからのものと一致しなければならないと仮定することの罠に陥らないでください。

14
jaco0646

わかりやすくするために、この例を検討してください。

電気通信会社は何を提供しますか?たとえば、ブロードバンド、電話回線、モバイルなどの場合、自社製品を顧客に提供するためのアプリケーションを作成するよう求められます。

一般的にここでは、ブロードバンド、電話回線、モバイルなどの製品の作成は、ファクトリメソッドを通じて行われます。それらの製品はとても簡単です。

今、同社は、顧客に自社製品のバンドル、すなわちブロードバンド、電話回線、およびモバイルをすべて提供したいと考えています。ここで、Abstract Factoryでプレーします。 。

抽象ファクトリーは、言い換えれば、自社製品の作成を担当する他の工場の構成であり、 Abstract Factoryは、自らの責任に関してこれらの製品をより意味のあるものにする方法を知っています。

この場合、BundleFactoryは抽象ファクトリ、BroadbandFactoryPhonelineFactoryおよびMobileFactoryFactoryです。より単純化するために、これらのファクトリは個々の製品を初期化するためにファクトリメソッドを持つでしょう。

以下のコードサンプルを見てください。

public class BroadbandFactory : IFactory {
    public static Broadband CreateStandardInstance() {
        // broadband product creation logic goes here
    }
}

public class PhonelineFactory : IFactory {
    public static Phoneline CreateStandardInstance() {
        // phoneline product creation logic goes here
    }
}

public class MobileFactory : IFactory {
    public static Mobile CreateStandardInstance() {
        // mobile product creation logic goes here
    }
}

public class BundleFactory : IAbstractFactory {

    public static Bundle CreateBundle() {
        broadband = BroadbandFactory.CreateStandardInstance();
        phoneline = PhonelineFactory.CreateStandardInstance();
        mobile = MobileFactory.CreateStandardInstance();

        applySomeDiscountOrWhatever(broadband, phoneline, mobile);
    }

    private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
        // some logic here
        // maybe manange some variables and invoke some other methods/services/etc.
    }
}

お役に立てれば。

10
Abdul Munim

クラスAはインタフェースBでプログラムされているので、プロダクションコードではほとんどの場合、抽象ファクトリパターンを使用します。また、AにはBのインスタンスを作成する必要があります。したがって、AはBの具体的なインスタンスに依存しません。

3
Adrian Liu

動機の違いを理解する:

オブジェクトを作成するツールと、オブジェクトの相互関係の具体的な実装を構築しているとします。オブジェクトのバリエーションを予測するため、オブジェクトのバリアントを作成する責任を別のオブジェクトに割り当てることにより、間接性を作成しました(抽象ファクトリーと呼びます)。これらのオブジェクトのバリアントを必要とする将来の拡張機能を予測するため、この抽象化には大きな利点があります。

この一連の考え方におけるもう1つのやや興味をそそる動機は、グループ全体のオブジェクトのすべてまたはすべてに対応するバリアントがある場合です。いくつかの条件に基づいて、いずれかのバリアントが使用され、それぞれの場合、すべてのオブジェクトは同じバリアントである必要があります。これは、オブジェクトのバリアントが共通の統一コントラクト(広い意味でのインターフェース)に従う限り、具体的な実装コードであるとよく考えられるため、理解するのは少し直感的ではありません。決して壊さないでください。ここで興味深い事実は、特に期待される動作をプログラミングコントラクトでモデル化できない場合、これが常に当てはまるわけではないということです。

シンプルな(GoFからアイデアを借りる)は、MSまたはMacまたはFedora OSのルックアンドフィールをエミュレートする仮想モニターと呼ばれるGUIアプリケーションです。ここで、たとえば、ウィンドウ、ボタンなどのすべてのウィジェットオブジェクトに、MACバリアントから派生したスクロールバーを除くMSバリアントがある場合、ツールの目的はひどく失敗します。

これらの上記のケースは、Abstract Factory Patternの基本的なニーズを形成します。

一方、多くの人がフレームワークを使用してさまざまなツール(上記の例など)を構築できるように、フレームワークを書いていると想像してください。フレームワークのアイデアそのものにより、ロジックで具体的なオブジェクトを使用することはできませんが、その必要はありません。むしろ、さまざまなオブジェクトとそれらの相互作用の間にいくつかの高レベルのコントラクトを配置します。あなた(フレームワーク開発者として)は非常に抽象的なレベルにとどまりますが、ツールの各ビルダーはあなたのフレームワーク構造に従うことを強制されます。ただし、(ツールビルダー)は、ビルドするオブジェクトと、作成するすべてのオブジェクトがどのように相互作用するかを自由に決定できます。前のケース(Abstract Factory Pattern)とは異なり、あなたは(フレームワーク作成者)として、この場合、具体的なオブジェクトを操作する必要はありません。むしろオブジェクトの契約レベルにとどまることができます。さらに、前の動機の2番目の部分とは異なり、ユーザーまたはツールビルダーは、バリアントからオブジェクトを混在させる状況に陥ることはありません。ここでは、フレームワークコードはコントラクトレベルのままですが、すべてのツールビルダーは(ケース自体の性質により)独自のオブジェクトの使用に制限されています。この場合のオブジェクト作成は各実装者に委任され、フレームワークプロバイダーはオブジェクトを作成して返すための統一されたメソッドを提供するだけです。このようなメソッドは、フレームワーク開発者がコードを進めるために必然であり、Factory method基礎となるパターンのファクトリメソッドパターン)と呼ばれる特別な名前を持っています。

注意点:

  • 「テンプレートメソッド」に精通している場合は、フレームワークの形式に関係するプログラムの場合、ファクトリメソッドはテンプレートメソッドから呼び出されることがよくあります。対照的に、アプリケーションプログラムのテンプレートメソッドは、多くの場合、特定のアルゴリズムの単純な実装であり、ファクトリメソッドはありません。
  • さらに、思考を完全にするために、フレームワーク(上記の)を使用して、ツールビルダーが具体的なオブジェクトを作成する代わりに、各ファクトリメソッド内でツールを構築している場合、 /彼女は、ツールビルダーが将来の拡張のために具体的なオブジェクトのバリエーションを予見する場合、責任を抽象ファクトリオブジェクトにさらに委任することができます。

サンプルコード:

//Part of framework-code
BoardGame {
    Board createBoard() //factory method. Default implementation can be provided as well
    Piece createPiece() //factory method

    startGame(){        //template method
         Board borad = createBoard()
         Piece piece = createPiece()
         initState(board, piece)
    }
}


//Part of Tool-builder code
Ludo inherits  BoardGame {
     Board createBoard(){ //overriding of factory method
         //Option A: return new LudoBoard() //Lodu knows object creation
         //Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
     }
….
}

//Part of Tool-builder code
Chess inherits  BoardGame {
    Board createBoard(){ //overriding of factory method
        //return a Chess board
    }
    ….
}
3
KGhatak
  1. 私の最初の質問は抽象ファクトリーについてです。その役割は、1つの具象オブジェクトではなく、具体的なオブジェクトのファミリを作成することを許可することです(使用する特定のファクトリによって異なります)。

はい。抽象ファクトリーの意図は以下のとおりです。

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


  1. 抽象ファクトリは、どのメソッドを呼び出すかに応じて、1つの非常に大きなオブジェクトまたは多くのオブジェクトのみを返しますか?

クライアントが呼び出しているメソッドごとに1つのオブジェクトを返すのが理想的です。

  1. 私の理解するところでは、ファクトリメソッドパターンには、ConcreteCreatorがどのConcreteProductをインスタンス化するかを知る責任を負うようにするCreatorインターフェースがあります。これは、オブジェクトのインスタンス化を処理するために継承を使用することによって何を意味するのでしょうか。

はい。ファクトリメソッドは継承を使用します

  1. 抽象ファクトリーパターンは、合成によって別のオブジェクトにオブジェクトのインスタンス化の責任を委任しますか?これは何を意味するのでしょうか?

AbstractFactoryはFactoryMethodを定義し、ConcreteFactoryはConcreteProductの構築を担当します。この記事 のコード例をたどってください。

あなたは関連するSE記事でより多くの詳細を見つけることができます:

FactoryとAbstract Factoryのパターンの基本的な違いは何ですか?

デザインパターン:Factory vs Factoryメソッドvs Abstract Factory

3
Ravindra babu

最小限のインターフェースで非常にシンプルにするには、 "// 1"に注目してください。

class FactoryProgram
    {
        static void Main()
        {
            object myType = Program.MyFactory("byte");
            Console.WriteLine(myType.GetType().Name);

            myType = Program.MyFactory("float"); //3
            Console.WriteLine(myType.GetType().Name);

            Console.ReadKey();
        }

        static object MyFactory(string typeName)
        {
            object desiredType = null; //1
            switch (typeName)
            {
                case "byte": desiredType = new System.Byte(); break; //2
                case "long": desiredType = new System.Int64(); break;
                case "float": desiredType = new System.Single(); break;
                default: throw new System.NotImplementedException();
            }
            return desiredType;
        }
    }

重要な点は次のとおりです。1. Factory&AbstractFactoryメカニズムは継承を使用する必要があります(System.Object-> byte、float ...)。したがって、プログラムに継承がある場合は、Factory(Abstract Factoryはおそらく存在しないはずです)は、設計上すでに存在しています2。抽象ファクトリでは戻り型はインタフェースになります。

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
    {
        IVehicle CreateSingleVehicle(string vehicleType);
    }
class HondaFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports": return new SportsBike();
                case "Regular":return new RegularBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }
class HeroFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports":  return new SportsBike();
                case "Scooty": return new Scooty();
                case "DarkHorse":return new DarkHorseBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }

class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }

class Program
{
    static void Main(string[] args)
    {
        IVehicleFactory honda = new HondaFactory(); //1
        RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
        SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
        Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);

        IVehicleFactory hero = new HeroFactory();
        DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
        SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
        Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
        Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);

        Console.ReadKey();
    }
}

重要なポイント:1。要件:ホンダは "通常"、 "スポーツ"を作成しますが、ヒーローは "ダークホース"、 "スポーツ"と "スクーティ"を作成します。なぜ2つのインタフェース? 1つは製造元タイプ(IVehicleFactory)、もう1つは製品工場(IVehicle)です。 2つのインタフェースを理解するための他の方法は、抽象ファクトリがすべて関連オブジェクトを作成することです。だから私は親変数(IVehicle)を取得します。それから私はCreateSingleVehicleを呼び出してそして実際の子オブジェクトに親オブジェクトをキャストすることによって実際の具象型を作成します。 RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");を実行するとどうなりますか。 ApplicationExceptionが発生します。そのため、必要に応じて説明する汎用の抽象ファクトリが必要です。初心者から中級者までお役に立てば幸いです。

2
Saurabh

実生活の例です。 (覚えやすい)

工場

あなたが家を建設していて、あなたがドアのために大工に近づくと想像してみてください。あなたはドアとあなたの要求のために寸法を与えます、そして彼はあなたのためにドアを作ります。この場合、大工はドアの工場です。あなたの仕様は工場への入力であり、ドアは工場からの出力または製品です。

抽象的なファクトリー

それでは、ドアの同じ例を考えてみましょう。あなたは大工に行くことができます、またはあなたはプラスチック製のドアショップまたはPVCショップに行くことができます。それらはすべてドア工場です。状況に基づいて、どの種類の工場にアプローチする必要があるかを決定します。これは抽象ファクトリーのようなものです。

ここでは、ファクトリメソッドパターンと抽象ファクトリパターンの両方を、問題を説明することを使わずに上記のパターンを使って問題を解決することから始めて説明しました 。/tree/master

私はいつでもFactory MethodよりAbstract Factoryを支持するでしょう。上記のTom Dallingの例(素晴らしい説明)から、抽象ファクトリは、異なるファクトリをコンストラクタに渡す(ここで使用されているコンストラクタ依存性注入)ことができるという点で、より構成可能であることがわかります。しかし、Factory Methodでは、新しいクラス(より多くの管理対象)を導入し、サブクラス化を使用する必要があります。継承よりも合成を優先します。

0
he9lin

ファクトリメソッドは継承に依存します。オブジェクトの作成はサブクラスに委譲され、サブクラスはファクトリメソッドを実装してオブジェクトを作成します。

抽象ファクトリはオブジェクト構成に依存します。オブジェクト作成はファクトリインタフェースで公開されているメソッドで実装されています。

工場および抽象的な工場パターンの高レベル図

diagram

Factoryメソッドの詳細については、この記事を参照してください。

Abstract factory methodの詳細については、この記事を参照してください。

0
user2266614

正確に言えばほとんどの回答はすでに説明されており、図表と例も提供されています。だから私の助言はただ一つのライナーになるでしょう。私自身の言葉: - 「抽象​​ファクトリパターンは、複数のファクトリメソッドの実装にまたがって抽象レイヤを追加します。抽象ファクトリには、1つまたは複数のファクトリメソッドパターンが含まれる、または複合されることを意味します。

0
King

上記の回答の多くは、抽象ファクトリとファクトリメソッドパターンの間のコード比較を提供しません。以下は、Javaでそれを説明しようとしている私の試みです。簡単な説明が必要な人に役立つことを願っています。

GoFが適切に言っているように:Abstract Factoryは、具象クラスを指定せずに、関連または従属オブジェクトのファミリーを作成するためのインターフェースを提供します。

        public class Client {
            public static void main(String[] args) {
               ZooFactory zooFactory = new HerbivoreZooFactory();       
               Animal animal1 = zooFactory.animal1();
               Animal animal2 = zooFactory.animal2();
               animal1.sound();
               animal2.sound();

               System.out.println();

               AnimalFactory animalFactory = new CowAnimalFactory();
               Animal animal = animalFactory.createAnimal();
               animal.sound();
            }
        }

        public interface Animal {
            public void sound();
        }

        public class Cow implements Animal {

            @Override
            public void sound() {
                System.out.println("Cow moos");
            }

        }

        public class Deer implements Animal {

            @Override
            public void sound() {
                System.out.println("Deer grunts");
            }

        }

        public class Hyena implements Animal {

            @Override
            public void sound() {
                System.out.println("Hyena.Java");
            }

        }

        public class Lion implements Animal {

            @Override
            public void sound() {
                System.out.println("Lion roars");
            }

        }

        public interface ZooFactory {
            Animal animal1();

            Animal animal2();
        }

        public class CarnivoreZooFactory implements ZooFactory {

            @Override
            public Animal animal1() {
                return new Lion();
            }

            @Override
            public Animal animal2() {
                return new Hyena();
            }

        }

        public class HerbivoreZooFactory implements ZooFactory{

            @Override
            public Animal animal1() {
                return new Cow();
            }

            @Override
            public Animal animal2() {
                return new Deer();
            }

        }

        public interface AnimalFactory {
            public Animal createAnimal();
        }

        public class CowAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Cow();
            }

        }

        public class DeerAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Deer();
            }

        }

        public class HyenaAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Hyena();
            }

        }

        public class LionAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Lion();
            }

        }
0
Jatin Shashoo

抽象ファクトリー:工場のファクトリー。具体的なクラスを指定せずに、個々の、ただし関連/従属工場をグループ化するファクトリ。 抽象ファクトリーの例

Factory:インスタンス化ロジックを子クラスに委任する方法を提供します。 工場パターン例

0
Atul Jain