注意:问题在帖子的末尾。
我已阅读有关抽象工厂与工厂方法的其他stackoverflow线程。我理解每个模式的意图。但是,我不清楚这个定义。
Factory Method定义了一个接口 用于创建对象,但让我们 子类决定了哪些 实例。工厂方法让 类推迟实例化 子类。
相比之下,一个抽象工厂 提供创建界面 相关或依赖的家庭 没有指定它们的对象 具体课程。
抽象工厂看起来非常类似于工厂方法。我已经绘制了一些UML类来说明我的观点。
注意:
工厂方法:
抽象工厂(仅限1名成员):
抽象工厂(更多成员):
问题:
答案 0 :(得分:131)
希望这会有所帮助。它描述了各种类型的工厂。我使用Head First Design Patterns作为参考。我使用yuml.me来绘制图表。
静态工厂
是一个具有静态方法的类,用于生成各种子类型的产品。
简单工厂
是一个可以生成各种子类型的产品的类。 (它比静态工厂更好。当添加新类型时,基础Product类不需要仅更改Simple Factory Class)
工厂方法
包含一种生成与其类型相关的产品类型的方法。 (它比简单工厂更好,因为类型被推迟到子类。)
抽象工厂
生成相关的类型系列。它与工厂方法明显不同,因为它有多种类型的方法。 (这很复杂,请参考下图,以获得更好的实际例子)。
.NET Framework示例
DbFactoriesProvider是一个简单工厂,因为它没有子类型。 DbFactoryProvider是一个抽象工厂,因为它可以创建各种相关的数据库对象,如连接和命令对象。
答案 1 :(得分:78)
这两种模式肯定是相关的!
模式之间的差异通常是意图。
工厂方法的意图是“定义用于创建对象的接口,但让子类决定实例化哪个类。工厂方法允许类将实例化延迟到子类。“
抽象工厂的意图是“提供用于创建相关或从属对象系列的接口,而无需指定其具体类。”
纯粹基于这些意图陈述(引自GoF),我会说,确实工厂方法在某种意义上是一个“退化”抽象工厂与一个家庭之一。
它们通常在实施方面有所不同,因为工厂方法比抽象工厂更简单。
然而,它们也与实施有关。正如GoF书中所述,
AbstractFactory仅声明用于创建产品的界面。由ConcreteProduct子类实际创建它们。最常见的方法是为每个产品定义工厂方法。
此c2 wiki也就此主题进行了一些有趣的讨论。
答案 2 :(得分:13)
似乎OP的(优秀)问题列表被忽略了。目前的答案仅提供重新定义的定义。因此,我将简要地尝试解决原始问题。
- 如果抽象工厂只有一个创作者和一个产品,它仍然是抽象工厂模式吗? (一个接口) 创造家庭)
醇>
没有。抽象工厂必须创建多个产品才能构成“相关产品系列”。规范的GoF示例创建ScrollBar()
和Window()
。优点(和目的)是抽象工厂可以在其多个产品中实施共同主题。
- 可以从接口创建工厂方法具体创建者还是必须来自某个类? (课程推迟 实例化到子类)
醇>
首先,我们必须注意,当GoF写下他们的书时,Java和C#都不存在。 GoF使用术语接口与特定语言引入的接口类型无关。因此,可以从任何API创建具体创建者。模式中的重点是API使用自己的工厂方法,因此只有一个方法的接口不能是工厂方法,而不能是抽象工厂。
- 如果抽象工厂只能有一个创建者和一个产品,那么抽象工厂与 工厂方法,前者的创建者是一个接口,后者的创建者是一个类?
醇>
根据上述答案,此问题不再有效;但是,如果您认为抽象工厂和工厂方法之间的唯一区别是创建的产品数量,请考虑客户端如何使用这些模式。抽象工厂通常被注入其客户端并通过组合/委托调用。必须继承工厂方法。所以这一切都回到了旧的构成与继承辩论。
但这些答案提出了第四个问题!
- 因为只有一种方法的界面不能是工厂方法,它可以是抽象工厂,我们做什么打电话给 创建界面只有一种方法?
醇>
如果方法是静态的,通常称为静态工厂。如果该方法是非静态的,则通常称为简单工厂。这些都不是GoF模式,但在实践中它们更常用!
答案 3 :(得分:4)
在我看来,两种模式之间的细微差别在于适用性,正如前面已经说过的那样,在 Intent 中。
让我们回顾一下定义(都来自维基百科)。
抽象工厂
为创建相关或从属对象族提供界面,而不指定其具体类。
工厂方法
定义用于创建对象的界面,但让实现该界面的类决定实例化哪个类。 Factory方法允许类将实例化延迟到子类。
这两种模式都允许将用户对象与创建所需实例(运行时解耦)分离,这是常见的方面。这两种模式都允许根据任何特定需求创建工厂层次结构,这是另一个常见方面。
Abstract Factory允许在一个子类中创建几种不同类型的实例,并在其不同的子类中具体化创建行为;通常,Factory方法声明只创建一种类型的对象,可以根据子类别机制进行细化。这就是区别。
总结。假设Product定义了创建对象的超类,ProductA和ProductB是两个不同的子类。因此,Abstract Factory方法将有两个方法,createProductA()和createProductB(),它们将在其特定的子类中具体化(就创建步骤而言):工厂子类特定于创建步骤用于创建的两个定义的对象类。
根据上面的示例,Factory方法将以不同的方式实现,在多个工厂(每个工厂一个方法)中抽象ProductA和ProductB的创建,以及创建步骤的进一步专业化将在构建时委托给层次结构。
答案 4 :(得分:2)
如果我创建了一个抽象的(通过接口或抽象基类引用) Factory类,它创建的对象只有一个方法来创建对象,那么它将是工厂方法< /强>
如果抽象工厂有多个方法来创建对象,那么它将是抽象工厂。
让我们说我创建了一个管理器来处理MVC控制器的动作方法的需要。 如果它有一个方法,比如说创建将用于创建视图模型的引擎对象,那么它将是一个工厂方法模式。 另一方面,如果它有两个方法:一个用于创建视图模型引擎,另一个用于创建动作模型引擎(或者您想要调用动作方法包含消费者的模型),那么它将是一个抽象工厂。 / p>
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);
}
答案 5 :(得分:1)
尽管如此,自从StackOverflow的人们在其他帖子(最早到2009年)中对此问题提出质疑以来已经很多年了,但我仍然找不到我想要的答案。
所以我通过网络进行了几个小时的研究,回顾了这些例子,并得出了这个结论,抽象工厂与工厂方法的主要区别是
反例是
因此,当最终对象组具有相同的样式而没有异常的对象并且您想隐藏这个“保持相同的样式”细节时,我们应该使用抽象工厂。 / p>
答案 6 :(得分:0)
据我理解抽象工厂和工厂方法定义的含义,第一个是在静态上下文中实现的,并根据输入参数提供对象。
第二个使用已经创建的对象(系列)来实现工厂方法接口。然后,工厂方法创建与原始对象相关的特定实例,无论它是哪一个。
因此,这通常会导致同时使用这两种模式,在第一步中,您将创建一些描述相关对象族的通用对象。它由静态方法getInstance(“我的姓氏”)方法调用。这种getInstance方法的实现决定了将创建哪个族对象。
然后我在新创建的族对象上调用createProduct()方法,并根据族对象返回新产品。
似乎这些模式与每个模式相互配合。
换句话说,抽象工厂专注于“什么”将被创建,工厂方法“如何”将被创建。
答案 7 :(得分:0)
您必须记住的是,抽象工厂是可以返回多个工厂的工厂。所以如果你有一个AnimalSpeciesFactory它可以返回这样的工厂:
Mamalfactory,BirdFactory,Fishfactory,ReptileFactory。既然您拥有AnimalSpeciesFactory中的单个工厂,他们就会使用工厂模式来创建特定的对象。例如,假设您从这个AnimalFactory获得了一个ReptileFactory,那么您可以提供创建爬行动物对象,如: 蛇,乌龟,蜥蜴对象。
答案 8 :(得分:0)
工厂方法模式是一种创建设计模式,它处理创建对象而不显示正在创建的对象的确切类。这种设计模式基本上允许类将实例化推迟到子类。
抽象工厂模式为一组单独的工厂提供封装,而不暴露具体类。在此模型中,抽象工厂类的通用接口用于创建所需的具体对象,将对象的实现细节与其使用和组合分开。此设计模式广泛用于需要创建类似GUI组件的GUI应用程序。
在谷歌搜索时,我出现了关注博客,这解释了两种设计模式。看看这些答案 9 :(得分: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;
}
*/