144

注:質問は投稿の最後にあります。

抽象ファクトリとファクトリメソッドに関する他のスタックオーバーフロースレッドを読みました。それぞれのパターンの意図を理解しています。しかし、その定義ははっきりしていません。

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

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

-ジョン・フェミネラ

抽象ファクトリファクトリメソッドと非常によく似ています。私の主張を説明するために、いくつかのUMLクラスを作成しました。

ノート:

  • この図はwww.yuml.comからのものであるため、完全に方向付けられているわけではありません。しかし、それは無料のサービスです:)。
  • ダイアグラムは完全ではない可能性があります。私はまだGoFデザインパターンを学んでいます。

ファクトリメソッド:

ファクトリメソッド

抽象ファクトリ(メンバーは1つのみ):

アブストラクトファクトリー(メンバーは1人のみ)

抽象ファクトリ(より多くのメンバー):

代替テキスト

質問:

  1. Abstract Factoryにクリエーターと製品が1つしかない場合でも、Abstract Factoryパターンですか?(家族を作成するためのインターフェース)
  2. ファクトリメソッドの具象作成者はインターフェイスから作成できますか、それともクラスから作成する必要がありますか?(クラスはインスタンス化をサブクラスに延期します)
  3. 抽象ファクトリが1つの作成者と1つの製品しか持てない場合、抽象ファクトリファクトリメソッドの唯一の違いは、前者の作成者がインターフェイスであり、後者の作成者がクラスであるということですか?
4

10 に答える 10

134

お役に立てれば。さまざまな種類の工場について説明します。参考として、Head FirstDesignPatternsの本を使用しました。ダイアグラム作成にはyuml.meを使用しました。

スタティックファクトリー

Productのさまざまなサブタイプを生成するための静的メソッドを持つクラスです。

スタティックファクトリー

シンプルファクトリー

製品のさまざまなサブタイプを生成できるクラスです。(静的ファクトリよりも優れています。新しいタイプが追加された場合、基本のProductクラスを変更する必要はなく、Simple Factoryクラスのみを変更する必要があります)

シンプルファクトリー

ファクトリメソッド

そのタイプに関連する1つのタイプの製品を生産するための1つのメソッドが含まれています。(タイプはサブクラスに延期されるため、Simple Factoryよりも優れています。)

ファクトリメソッド

抽象ファクトリ

関連するタイプのファミリーを生成します。生成するタイプのメソッドが複数あるため、ファクトリメソッドとは著しく異なります。(これは複雑です。実際の例については、次の図を参照してください)。

抽象ファクトリ

.NETFrameworkの例

DbFactoriesProviderは、サブタイプがないため、シンプルファクトリです。DbFactoryProviderは、接続オブジェクトやコマンドオブジェクトなど、さまざまな関連データベースオブジェクトを作成できるため、抽象ファクトリです。

.NETFrameworkの抽象ファクトリ </ p>

于 2010-11-18T03:03:52.003 に答える
82

2つのパターンは確かに関連しています!

パターン間の違いは、一般的に意図されています。

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

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

純粋にこれらの意図ステートメント(GoFから引用)に基づいて、ファクトリメソッドはある意味で1つのファミリを持つ「縮退した」抽象ファクトリであると言えます。

FactoryメソッドはAbstractFactoryよりもかなり単純であるため、これらは一般に実装が異なる傾向があります。

ただし、これらは実装にも関連しています。GoFの本に記載されているように、

AbstractFactoryは、製品を作成するためのインターフェースのみを宣言します。実際に作成するのはConcreteProductサブクラス次第です。これを行う最も一般的な方法は、各製品のファクトリメソッドを定義することです。

このc2wikiには、このトピックに関する興味深い議論もあります。

于 2010-11-17T23:11:28.757 に答える
17

OPの(優れた)質問のリストは無視されているようです。現在の回答は、再ハッシュされた定義を提供するだけです。そのため、元の質問に簡潔に対処するように努めます。

  1. Abstract Factoryにクリエーターと製品が1つしかない場合でも、Abstract Factoryパターンですか?(家族を作成するためのインターフェース)

いいえ。抽象ファクトリは、「関連製品のファミリ」を作成するために複数の製品を作成する必要があります。正規のGoFの例では、とを作成ScrollBar()Window()ます。利点(および目的)は、AbstractFactoryが複数の製品に共通のテーマを適用できることです。

  1. ファクトリメソッドの具象作成者はインターフェイスから作成できますか、それともクラスから作成する必要がありますか?(クラスはインスタンス化をサブクラスに延期します)

まず、GoFが本を書いたとき、JavaもC#も存在しなかったことに注意する必要があります。インターフェースという用語のGoFの使用は、特定の言語によって導入されたインターフェースタイプとは無関係です。したがって、具体的な作成者は任意のAPIから作成できます。このパターンの重要な点は、APIが独自のファクトリメソッドを使用するため、メソッドが1つしかないインターフェイスは、抽象ファクトリである以上にファクトリメソッドになることはできないということです。

  1. 抽象ファクトリが1つの作成者と1つの製品しか持てない場合、抽象ファクトリファクトリメソッドの唯一の違いは、前者の作成者がインターフェイスであり、後者の作成者がクラスであるということですか?

上記の回答に従って、この質問は無効になりました。ただし、AbstractFactoryとFactoryMethodの唯一の違いは作成された製品の数であると考えている場合は、クライアントがこれらの各パターンをどのように消費するかを検討してください。抽象ファクトリは通常、クライアントに注入され、構成/委任を介して呼び出されます。ファクトリメソッドを継承する必要があります。つまり、それはすべて、古い構成と継承の議論に戻ります。

しかし、これらの答えは4番目の質問を提起しました!

  1. メソッドが1つしかないインターフェイスは、抽象ファクトリある以上にファクトリメソッドになることはできないので、メソッドが1つしかない作成インターフェイスを何と呼びますか?

メソッドが静的である場合、それは一般に静的ファクトリと呼ばれます。メソッドが非静的である場合、それは一般にSimpleFactoryと呼ばれます。これらはどちらもGoFパターンではありませんが、実際にははるかに一般的に使用されています。

于 2016-07-29T22:17:01.990 に答える
4

私の意見では、2つのパターンのわずかな違いは適用性にあり、すでに述べたように、インテントにあります。

定義を要約してみましょう(両方ともウィキペディアから)。

抽象ファクトリ

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

ファクトリメソッド

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

どちらのパターンでも、ユーザーオブジェクトを必要なインスタンスの作成から切り離すことができ(実行時の切り離し)、これが一般的な側面です。どちらのパターンでも、特定のニーズに応じて工場の階層を作成できます。これは、もう1つの一般的な側面です。

Abstract Factoryを使用すると、1つのサブクラスで複数の異なるタイプのインスタンスを作成し、その異なるサブクラスで作成動作を特殊化できます。通常、ファクトリメソッドは、サブクラス化メカニズムに従って特定できる1つのタイプのオブジェクトのみの作成を宣言します。それが違いです。

要約することによって。Productが作成オブジェクトのスーパークラスを定義し、ProductAとProductBが2つの異なるサブクラスであるとしましょう。したがって、Abstract FactoryメソッドにはcreateProductA()とcreateProductB()の2つのメソッドがあり、これらは特定のサブクラスで(作成ステップに関して)特定されます。ファクトリサブクラスは、2つの定義されたクラスの作成ステップを特定します。作成中のオブジェクトの。

上記の例によると、ファクトリメソッドは異なる方法で実装され、同じ数のファクトリでProductAとProductBの作成を抽象化し(ファクトリごとに1つのメソッド)、作成ステップのさらなる特殊化は、構築時に階層に委任されます。

于 2014-04-28T09:29:30.073 に答える
2

オブジェクトを作成するためのメソッドが1つしかないオブジェクトを作成する抽象化された(インターフェイスまたは抽象基本クラスを介して参照される)ファクトリクラスを作成した場合、それはファクトリメソッドになります。

抽象化されたファクトリにオブジェクトを作成するための複数のメソッドがある場合、それは抽象ファクトリになります。

MVCコントローラーのアクションメソッドのニーズを処理するマネージャーを作成するとします。たとえば、ビューモデルの作成に使用されるエンジンオブジェクトを作成するメソッドが1つある場合、それはファクトリメソッドパターンになります。一方、ビューモデルエンジンを作成するメソッドと、アクションモデルエンジン(またはアクションメソッドにコンシューマーが含まれるモデルと呼びたいもの)を作成するメソッドの2つのメソッドがある場合、それは抽象ファクトリになります。

public ActionResult DoSomething(SpecificActionModel model)
{
    var actionModelEngine = manager.GetActionModelEngine<SpecificActionModel>();
    actionModelEngine.Execute(SpecificActionModelEnum.Value);

    var viewModelEngine = manager.GetViewModelEngine<SpecificViewModel>();
    return View(viewModelEngine.GetViewModel(SpecificViewModelEnum.Value);
}
于 2012-12-20T08:09:32.143 に答える
1

StackOverflowの人々が他の投稿でも同様にこの問題について質問してから何年も経ちますが(最も古いのは2009年です)、それでも私が望む答えを見つけることができませんでした。


そこで、Webを介して数時間調査し、例を確認して、この結論に達しました。AbstractFactoryとFactoryMethodの主な違いは次のとおりです。

  • 意図:一貫性または「ルックアンドフィール」:Abstract Factoryの意図は、同じスタイルのオブジェクトのファミリをグループ化することです(たとえば、同じルックアンドフィールのUIウィジェット、同じスタイルの自動車部品、同じOSのオブジェクト、など)Abstract Factoryの多くの例では、「同じルックアンドフィール」というキーフレーズについて言及しています。
  • より大きなグループオブジェクトを形成するオブジェクト:Abstract Factoryは、単一のオブジェクトではなく、より大きなグループオブジェクトを形成するオブジェクトのファミリーを作成します。
  • 後で新しいスタイルを追加する:ファクトリメソッドを使い続けて、既存のインフラストラクチャに新しいスタイルのセットを追加しようとすると、苦痛になります。Abstract Factoryを使用すると、抽象ファクトリクラスを実装する新しい具象ファクトリを作成するだけで済みます。

反例は次のようになります

  • セダンで使用されるスポーツカー用の自動車部品。この不一致は事故につながる可能性があります。
  • さまざまなOSGUIウィジェットのWindowsスタイルのボタン。それは何も壊すことはありませんが、私のような一部の人々のユーザーエクスペリエンスを損なうことはありません。
  • 後で、ソフトウェアの下位互換性を維持しながら、互換性のあるシステムオブジェクトの異なるセットを必要とする次のOSアップグレードでソフトウェアを実行する必要があることがわかりました。

したがって、最終的なオブジェクトグループがオブジェクトを除いて同じスタイルを持つ必要があり、この「同じスタイルを維持する」詳細を非表示にする場合は、AbstractFactoryを使用する必要があります。

于 2016-06-01T15:00:57.710 に答える
0

私が理解している限り、o抽象ファクトリとファクトリメソッドの定義は、静的コンテキストで実装され、入力パラメータに基づいてオブジェクトを提供します。

2つ目は、ファクトリメソッドインターフェイスを実装する作成済みのオブジェクト(ファミリ)を使用します。次に、ファクトリメソッドは、元のオブジェクトがどれであるかに関係なく、元のオブジェクトに関連する特定のインスタンスを作成します。

したがって、これは通常、両方のパターンを一緒に使用することにつながります。最初のステップで、関連するオブジェクトのファミリーを説明する一般的なオブジェクトを作成します。これは、静的メソッドgetInstance( "my family name")メソッドによって呼び出されます。このようなgetInstanceメソッドの実装により、作成されるファミリオブジェクトが決まります。

次に、新しく作成されたファミリオブジェクトに対してcreateProduct()メソッドを呼び出します。ファミリオブジェクトに応じて、新しい製品が返されます。

これらのパターンはそれぞれに協力しているようです。

つまり、Abstract Factoryは「WHAT」が作成され、Factoryメソッド「HOW」が作成されることに焦点を当てています。

于 2013-06-16T15:39:54.350 に答える
0

覚えておく必要があるのは、抽象ファクトリは複数のファクトリを返すことができるファクトリであるということだけです。したがって、AnimalSpeciesFactoryがある場合は、次のようなファクトリを返すことができます。

Mamalfactory、BirdFactory、Fishfactory、ReptileFactory。これで、AnimalSpeciesFactoryから単一のファクトリが作成されたので、ファクトリパターンを使用して特定のオブジェクトを作成します。たとえば、このAnimalFactoryからReptileFactoryを取得した場合、ヘビ、カメ、トカゲのオブジェクトなどの爬虫類オブジェクトの作成を提案できます。

于 2016-02-08T16:52:20.803 に答える
0
/*
//Factory methods:

//1. Factory Method - Abstract Creator Class



#include <iostream>
#include <string.h>
using namespace std;

const std::string nineNintyCC = std::string("990CC");
const std::string thousandTwoHundredCC = std::string("1200CC");
const std::string ThousandFiveHundredCC = std::string("1500CC");
const std::string fiveThousandCC = std::string("5000CC");

// Product
class Engine
{
    public:
    virtual void packEngine() = 0;  
};

// Concrete products
// concrete product class one
class C990CCEngine: public Engine
{

    public:
    void packEngine()
    {
       cout << "Pack 990CC engine" << endl;   
    }
};

// concrete class Two
class C1200CCEngine: public Engine
{   public:
    void packEngine()
    {
        cout << "pack 1200CC engine" << endl;
    }

};

// Concrete class Three
class C1500CCEngine: public Engine
{
    public:
    void packEngine()
    {
        cout << "Pack 1500CC engine" << endl;
    }

};


// Car Factory:
class CarFactory{
    public:

    virtual Engine* createEngine(const std::string& type) = 0;
};
class Factory: public CarFactory
{
    public:
     Engine *createEngine(const std::string& type)
     {

          if(0 == nineNintyCC.compare(type))
          {    
             return new C990CCEngine;
          }
          else if(0 == thousandTwoHundredCC.compare(type))
          {
             return new C1200CCEngine;
          }
          else if(0 == ThousandFiveHundredCC.compare(type))
          {
             return new C1500CCEngine;
          } 
          else
           {
                 cout << "Invalid factory input" << endl;
             return NULL;
           }
           return NULL;
     }
};

int main()
{

    CarFactory* ptr = new Factory;
    Engine*pEngine =  ptr->createEngine(nineNintyCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine =  ptr->createEngine(ThousandFiveHundredCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine =  ptr->createEngine(thousandTwoHundredCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    pEngine = ptr-> createEngine(fiveThousandCC);
    if(pEngine)
    {
        pEngine->packEngine();
        delete pEngine;
    }
    else
    {
        cout << "No engine exists of your type in our factory" << endl;
    }
    return 0;
}

*/
/*
//
// interface product
#include <iostream>
#include <string>
using namespace std;

class Engine
{
 public:
 virtual void EngineType() = 0;

};

// concrte product
class AltoEngine: public Engine
{
  public:
  void EngineType()
  {
      cout << "Alto Engine" << endl;
  }
};

//Concrte product
class SwiftEngine : public Engine
{
    public:
    void EngineType()
    {
        cout << "Swift Engine" << endl;    
    }
};

class Body
{
   public:
    virtual void bodyType() = 0;

};

class AltoBody: public Body
{
  public:  
    virtual void bodyType()
    {
        cout << "Alto Car Body" << endl;
    }
};

class SwiftBody : public Body
{
    public:
    void bodyType()
    {
        cout << "SwiftCar Body" << endl;
    }

};


class CarFactory
{
   public:
   virtual Engine* createEngineProduct() = 0;
   virtual Body*   createBodyPoduct() = 0;
};
class AltoCarFactory: public CarFactory
{
    public:
    Engine * createEngineProduct()
    {
        return new AltoEngine;
    }
    Body* createBodyPoduct()
    {
        return new AltoBody;
    }

};

class SwiftCarFactory: public CarFactory
{
    public:
    Engine * createEngineProduct()
    {
        return new SwiftEngine;
    }
    Body* createBodyPoduct()
    {
        return new SwiftBody;
    }

};

int main()
{

    CarFactory* pAltoFactory = new AltoCarFactory;
    Engine* pAltoEngine = pAltoFactory->createEngineProduct();
    pAltoEngine->EngineType();
    Body* pAltoBody = pAltoFactory->createBodyPoduct();
    pAltoBody->bodyType();



    CarFactory* pSwiftFactory = NULL;
    pSwiftFactory = new SwiftCarFactory;
    Engine* pSwiftEngine = pSwiftFactory->createEngineProduct();
    pSwiftEngine->EngineType();
    Body* pSwfitBody = pSwiftFactory->createBodyPoduct();
    pSwfitBody->bodyType();
    delete pAltoBody;
    delete pAltoFactory;
    delete pSwfitBody;
    delete pSwiftFactory;
    return 0;
}
*/

/*

// One more Factory example;

#include <iostream>
#include <string>
using namespace std;

const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");
// Interface
class CarEngine
{
 public:
    virtual void engineType() = 0;
};

// Concrete class
class FiatEngine: public CarEngine
{
  public:
  void engineType()
  {
      cout << "Fait Engine Engine" << endl;
  }

};
// ConcreteClass
class RenaultEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Renault Engine" << endl;
    }

};
// Concrete class
class MaruthiEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Maruthi Engine" << endl;
    }
};


// Factory
class CarFactory
{
    public:
    virtual CarEngine* createFactory(const std::string&) = 0;
};

// EngineFactory
class CarEngineFactory : public CarFactory
{
     public:
     CarEngine* createFactory(const std::string&  type)
     {
          if(0 == maruthi.compare(type))
          {
              return new MaruthiEngine;

          }
          else if(0 == fiat.compare(type))
          {
              return  new FiatEngine;
          }
          else if(0 == renault.compare(type))
          {
              return new RenaultEngine;
          }
          else
          {
              cout << "Invalid Engine type" << endl;
              return NULL;
          }
     }

  };

int main()
{
    CarFactory* pCarFactory = new CarEngineFactory;
    CarEngine* pMaruthiCarEngine = pCarFactory->createFactory(maruthi);
    pMaruthiCarEngine->engineType();

    CarEngine* pFiatCarEngine = pCarFactory->createFactory(fiat);
    pFiatCarEngine->engineType();


    CarEngine* pRenaultCarEngine = pCarFactory->createFactory(renault);
    pRenaultCarEngine->engineType();

    return 0;
}


*/


/*

// One more Factory example;

#include <iostream>
#include <string>
using namespace std;

const std::string maruthi = std::string("Maruthi");
const std::string fiat = std::string("Fiat");
const std::string renault = std::string("Renault");


// Interface
class CarEngine
{
 public:
    virtual void engineType() = 0;
};

// Concrete class
class FiatEngine: public CarEngine
{
  public:
  void engineType()
  {
      cout << "Fait Car Engine" << endl;
  }

};

// ConcreteClass
class RenaultEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Renault Car Engine" << endl;
    }

};

// Concrete class
class MaruthiEngine : public CarEngine
{
    public:
    void engineType()
    {
        cout << "Maruthi Car Engine" << endl;
    }
};

// Interface
class CarBody
{
 public:
    virtual void bodyType() = 0;
};

// Concrete class
class FiatBody: public CarBody
{
  public:
  void bodyType()
  {
      cout << "Fait car Body" << endl;
  }

};

// ConcreteClass
class RenaultBody : public CarBody
{
    public:
    void bodyType()
    {
        cout << "Renault Body" << endl;
    }

};

// Concrete class
class MaruthiBody : public CarBody
{
    public:
    void bodyType()
    {
        cout << "Maruthi body" << endl;
    }
};


// Factory
class CarFactory
{
    public:
    virtual CarEngine* createCarEngineProduct() = 0;
    virtual CarBody* createCarBodyProduct() = 0;
};

// FiatFactory
class FaitCarFactory : public CarFactory
{
     public:
     CarEngine* createCarEngineProduct()
     {
        return new FiatEngine; 
     }
     CarBody* createCarBodyProduct()
     {
         return new FiatBody;
     }
};

// Maruthi Factory
class MaruthiCarFactory : public CarFactory
{
     public:
     CarEngine* createCarEngineProduct()
     {
         return new MaruthiEngine;
     }
     CarBody* createCarBodyProduct()
     {
         return new MaruthiBody;
     }

};

// Renault Factory
class RenaultCarFactory : public CarFactory
{
     public:
    CarEngine* createCarEngineProduct()
    {
        return new RenaultEngine;
    }

    CarBody* createCarBodyProduct()
    {
        return new RenaultBody;
    }

};


int main()
{

   // Fiat Factory
   CarFactory* pFiatCarFactory = new FaitCarFactory;
   CarEngine* pFiatEngine = pFiatCarFactory->createCarEngineProduct();
   CarBody*  pFiatBody = pFiatCarFactory->createCarBodyProduct();
   pFiatEngine->engineType();
   pFiatBody->bodyType();

   // Renault Car Factory
    return 0;
}

*/
于 2018-04-25T16:56:08.903 に答える
-1

ファクトリメソッドパターンは、作成中のオブジェクトの正確なクラスを表示せずにオブジェクトの作成を処理する作成デザインパターンです。このデザインパターンにより、基本的に、クラスはインスタンス化をサブクラスに延期することができます。

Abstract Factoryパターンは、具体的なクラスを公開せずに、個々のファクトリのグループにカプセル化を提供します。このモデルでは、抽象ファクトリクラスの汎用インターフェイスを使用して、オブジェクトの実装の詳細をその使用法および構成から分離するために必要な具体的なオブジェクトを作成します。このデザインパターンは、同様の種類のGUIコンポーネントを作成する必要があるGUIアプリケーションで広く使用されています。

于 2016-12-28T11:24:02.623 に答える