144

注:问题在文末。

我已经阅读了有关Abstract Factory vs Factory Method的其他 stackoverflow 线程。我了解每种模式的意图。但是,我不清楚定义。

工厂方法定义了一个用于创建对象的接口,但让子类决定要实例化哪些接口。工厂方法允许类将实例化推迟到子类。

相比之下,抽象工厂提供了一个接口,用于创建相关或依赖对象的系列,而无需指定它们的具体类。

——约翰·费米内拉

抽象工厂看起来与工厂方法非常相似。我画了几个 UML 类来说明我的观点。

笔记:

  • 该图来自www.yuml.com,因此它们的方向并不完美。但它是一项免费服务:)。
  • 图表可能并不完美。我仍在学习GoF设计模式。

工厂方法:

工厂方法

抽象工厂(只有 1 名成员):

抽象工厂(仅 1 名成员)

抽象工厂(更多成员):

替代文字

问题:

  1. 如果抽象工厂只有一个创造者和一个产品,那还是抽象工厂模式吗?(创建家庭的界面)
  2. 工厂方法具体创建者可以从接口创建还是必须来自类?(类将实例化推迟到子类)
  3. 如果抽象工厂只能有一个创建者和一个产品,那么抽象工厂工厂方法的唯一区别是前者的创建者是一个接口,后者的创建者是一个类吗?
4

10 回答 10

134

希望这可以帮助。它描述了各种类型的工厂。我使用Head First Design Patterns这本书作为参考。我用yuml.me来绘制图表。

静态工厂

是一个具有静态方法的类,用于生产产品的各种子类型。

静态工厂

简单工厂

是一个可以产生各种子类型Product的类。(它比静态工厂好。当添加新类型时,基产品类不需要更改,只需简单工厂类)

简易工厂

工厂方法

包含一种生产与其类型相关的一种产品的方法。(它比简单工厂更好,因为类型被推迟到子类。)

工厂方法

抽象工厂

产生一系列相关的类型。它与工厂方法明显不同,因为它产生的类型方法不止一种。(这很复杂,请参阅下一张图以获得更好的现实示例)。

抽象工厂

来自 .NET Framework 的示例

DbFactoriesProvider 是一个简单工厂,因为它没有子类型。DbFactoryProvider 是一个抽象工厂,因为它可以创建各种相关的数据库对象,例如连接和命令对象。

.NET Framework 的抽象工厂 ​​​​</p>

于 2010-11-18T03:03:52.003 回答
82

这两种模式肯定是相关的!

模式之间的差异通常在于意图。

工厂方法意图是“定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法让一个类将实例化推迟到子类。”

抽象工厂目的是“为创建相关或依赖对象系列提供一个接口,而无需指定它们的具体类。”

纯粹基于这些意图陈述(引自 GoF),我会说工厂方法在某种意义上确实是一个“退化的”抽象工厂,拥有一个家族。

它们通常在实现上往往有所不同,因为Factory MethodAbstract Factory简单得多。

然而,它们在实施中也相关。如 GoF 书中所述,

AbstractFactory 只声明了一个用于创建产品的接口。由 ConcreteProduct 子类来实际创建它们。最常见的方法是为每个产品定义一个工厂方法。

这个c2 wiki也有关于这个主题的一些有趣的讨论。

于 2010-11-17T23:11:28.757 回答
17

似乎OP的(优秀)问题列表已被忽略。当前的答案仅提供重新定义的定义。因此,我将尝试简明扼要地解决最初的问题。

  1. 如果抽象工厂只有一个创造者和一个产品,那还是抽象工厂模式吗?(创建家庭的界面)

没有。一个抽象工厂必须创造一个以上的产品来制造一个“相关产品系列”。规范的 GoF 示例创建ScrollBar()Window(). 优点(和目的)是抽象工厂可以在其多个产品中强制执行一个共同的主题。

  1. 工厂方法具体创建者可以从接口创建还是必须来自类?(类将实例化推迟到子类)

首先,我们必须注意,当 GoF 写他们的书时,Java 和 C# 都不存在。GoF 对术语接口的使用与特定语言引入的接口类型无关。因此,可以从任何 API 创建具体创建者。该模式的重点是 API 使用自己的工厂方法,因此只有一个方法的接口不能是工厂方法,也不能是抽象工厂。

  1. 如果抽象工厂只能有一个创建者和一个产品,那么抽象工厂工厂方法的唯一区别是前者的创建者是一个接口,后者的创建者是一个类吗?

按照上面的答案,这个问题不再有效;但是,如果您认为抽象工厂和工厂方法之间的唯一区别是创建的产品数量,请考虑客户如何使用这些模式。抽象工厂通常被注入其客户端并通过组合/委托调用。必须继承工厂方法。所以这一切都回到了旧的组合与继承的争论。

但这些答案提出了第四个问题!

  1. 既然只有一种方法的接口不能是工厂方法,也不能是抽象工厂那么我们怎么称呼只有一种方法的创建接口呢?

如果方法是静态的,则通常称为静态工厂。如果该方法是非静态的,则通常称为Simple Factory。这些都不是 GoF 模式,但在实践中它们更常用!

于 2016-07-29T22:17:01.990 回答
4

在我看来,这两种模式之间的细微差别在于适用性,正如已经说过的,在Intent中也是如此。

让我们回顾一下定义(均来自维基百科)。

抽象工厂

提供用于创建相关或依赖对象系列的接口,而无需指定它们的具体类。

工厂方法

定义一个用于创建对象的接口,但让实现该接口的类决定实例化哪个类。Factory 方法允许类将实例化推迟到子类。

两种模式都允许将用户对象与创建所需的实例(运行时解耦)分离,这是共同的方面。两种模式都允许根据任何特定需求创建工厂层次结构,这是另一个共同方面。

抽象工厂允许在一个子类中创建几种不同类型的实例,并在其不同的子类中具体化创建行为;通常,Factory 方法只声明创建一种类型的对象,可以根据子类化机制进行具体化。这就是区别。

通过总结。假设 Product 定义了创建对象的超类,而 ProductA 和 ProductB 是两个不同的子类。因此,抽象工厂方法将有两个方法,createProductA() 和 createProductB(),它们将在其特定的子类中详细说明(在创建步骤方面):工厂子类详细说明了两个已定义类的创建步骤正在创建的对象。

根据上面的示例,Factory Method 的实现方式将有所不同,在尽可能多的工厂中抽象 ProductA 和 ProductB 的创建(每个工厂一个方法),并且创建步骤的进一步专业化将在构建时委托给层次结构.

于 2014-04-28T09:29:30.073 回答
2

如果我创建了一个抽象的(通过接口或抽象基类引用)工厂类,它创建的对象只有一种创建对象的方法,那么它将是一个工厂方法

如果抽象工厂有超过 1 种方法来创建对象,那么它将是一个抽象工厂

假设我创建了一个管理器来处理 MVC 控制器的操作方法需求。如果它有一种方法,比如创建将用于创建视图模型的引擎对象,那么它将是一种工厂方法模式。另一方面,如果它有两种方法:一种是创建视图模型引擎,另一种是创建动作模型引擎(或任何你想调用动作方法包含消费者的模型),那么它将是一个抽象工厂。

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 年),我仍然找不到我想要的答案。


所以我通过网络做了几个小时的研究,回顾了例子,得出了这个结论,抽象工厂与工厂方法的主要区别是

  • 意图:连贯性或“外观”:Abstract Factory 的意图是将一组具有相同样式的对象(例如,相同外观的 UI 小部件、相同样式的汽车部件、来自相同操作系统的对象、等等)来自抽象工厂的许多例子都提到了关键词“相同的外观和感觉”。
  • 对象形成一个更大的组对象:抽象工厂创建一个对象族,形成一个更大的组对象,而不是单个对象。
  • 稍后添加新样式:如果我们继续使用工厂方法并尝试在现有基础架构中添加一组新样式,那将是痛苦的。使用抽象工厂,我们只需创建一个新的具体工厂来实现抽象工厂类。

反例是

  • 用于轿车的跑车零件。这种不一致可能导致事故。
  • 不同操作系统 GUI 小部件中的 Windows 样式按钮。它不会破坏任何东西,但会损害某些人的用户体验,比如我。
  • 后来,我们发现我们的软件需要在下一次操作系统升级中运行,这需要不同的兼容系统对象集,同时保持软件向后兼容。

因此,当最终的对象组应该具有相同的样式,而没有一个对象例外,并且您想隐藏这个“保持相同样式”的细节,那么我们应该使用抽象工厂。

于 2016-06-01T15:00:57.710 回答
0

据我了解抽象工厂和工厂方法定义的含义,第一个是在静态上下文中实现的,并根据输入参数提供对象。

第二个使用实现工厂方法接口的已创建对象(家庭)。工厂方法然后创建与原始对象相关的特定实例,无论它是哪一个。

因此,这通常会导致同时使用这两种模式,在第一步中,您创建一些描述相关对象系列的通用对象。它由静态方法 getInstance("my family name") 方法调用。这种 getInstance 方法的实现决定了将创建哪个家庭对象。

然后我在新创建的家庭对象上调用 createProduct() 方法,并根据家庭对象返回新产品。

这些模式似乎相互配合。

换句话说,抽象工厂专注于将创建“什么”以及将创建工厂方法“如何”。

于 2013-06-16T15:39:54.350 回答
0

您必须记住的是,抽象工厂是可以返回多个工厂的工厂。所以如果你有一个 AnimalSpeciesFactory 它可以像这样返回工厂:

Mamalfactory,BirdFactory,Fishfactory,ReptileFactory。现在您已经拥有来自 AnimalSpeciesFactory 的单个工厂,它们使用工厂模式来创建特定的对象。例如,假设您从这个 AnimalFactory 获得了一个 ReptileFactory,那么您可以提供创建爬行动物对象,例如:Snakes、turtles、lizards 对象。

于 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

工厂方法模式是一种创建型设计模式,它处理创建对象而不显示正在创建的对象的确切类。这种设计模式基本上允许一个类将实例化推迟到子类。

抽象工厂模式用于封装一组单独的工厂,而不暴露具体的类。在该模型中,抽象工厂类的通用接口用于创建所需的具体对象,将对象的实现细节与其使用和组合分开。这种设计模式广泛用于需要创建类似类型的 GUI 组件的 GUI 应用程序中。

于 2016-12-28T11:24:02.623 回答