工厂和抽象工厂设计模式之间的基本区别是什么?

工厂模式和抽象工厂模式之间的基本区别是什么?

263013 次浏览

抽象工厂模式

  • 创建接口 亲缘或依赖的家庭 对象,而不指定 具体类。< / p >

  • 抽象工厂模式非常 类似于工厂方法 模式。一个区别是 二是抽象工厂 模式,类委托 客体责任 实例化到另一个对象 鉴于工厂 方法模式使用继承和 类依赖于子类来处理 需要的对象实例化
  • 实际上是委托对象 经常使用工厂方法来 执行实例化!< / p >

工厂模式

    工厂模式的例子 创建型模式< / p >
  • 创建模式抽象 对象实例化过程。他们 隐藏对象是如何创建和帮助的 使整个系统相互独立 它的对象是如何创建的 组成。< / p >

  • 类创建模式的重点 使用继承来决定 对象进行实例化 工厂方法< / p >
  • 对象创建模式所关注 实例化的委托 到另一个对象 抽象工厂< / p >

< p >参考: 工厂vs抽象工厂 < / p >
< p >工厂模式: 工厂生产IProduct-implementations

抽象工厂模式 factory-factory生成IFactories, IFactories又生成IProducts:)

< p > [根据评论更新] < br > 我之前写的至少根据维基百科是不正确的。抽象工厂就是一个简单的工厂接口。有了它,您可以在运行时切换工厂,以允许在不同的上下文中使用不同的工厂。例如针对不同操作系统的不同工厂、SQL提供者、中间件驱动程序等等。< / p >

使用Factory模式,可以生成特定接口(比如IFruit)的实现实例(AppleBananaCherry等)。

使用抽象工厂模式,您可以为任何人提供他们自己的工厂提供一种方法。这使得你的仓库既可以是IFruitFactory也可以是IJuiceFactory,而不需要你的仓库知道任何关于水果或果汁的信息。

此信息的来源来自:http://java.dzone.com/news/intro-design-patterns-abstract

抽象工厂与工厂方法

抽象工厂的方法被实现为工厂方法。抽象工厂模式和工厂方法模式都通过抽象类型和工厂将客户端系统与实际实现类解耦。 工厂方法通过继承创建对象,而抽象工厂通过组合创建对象

抽象工厂模式由AbstractFactory、ConcreteFactory、AbstractProduct、ConcreteProduct和客户端组成。

如何实现

抽象工厂模式可以使用工厂方法模式、原型模式或单例模式来实现。ConcreteFactory对象可以作为一个单例对象实现,因为只需要一个ConcreteFactory对象实例。

工厂方法模式是抽象工厂模式的简化版本。工厂方法模式负责创建属于一个家族的产品,而抽象工厂模式处理多个产品家族。

工厂方法使用接口和抽象类将客户端与生成器类和生成的产品解耦。摘要工厂有一个生成器,它是几个工厂方法的容器,以及将客户端与生成器和产品分离的接口。

何时使用工厂方法模式

当需要将客户端与其使用的特定产品解耦时,请使用工厂方法模式。使用Factory方法可以减轻客户端创建和配置产品实例的责任。

何时使用抽象工厂模式

当客户端必须与产品类解耦时,使用抽象工厂模式。 特别适用于程序配置和修改。抽象工厂模式还可以强制约束哪些类必须与其他类一起使用。建造新的混凝土工厂可能需要做很多工作

例子:

抽象工厂实例1

此规格用于制备不同类型的面食 在面食机中有一个抽象工厂,每个特定的圆盘都是一个工厂。 所有的工厂(意大利面食机磁盘)从抽象工厂继承他们的属性。 每个单独的磁盘都包含如何制作意大利面,而意大利面机没有

例子2:

冲压设备对应于抽象工厂,因为它是 用于创建抽象产品对象的操作接口。 模具对应混凝土工厂,因为他们创造一个混凝土产品。 每个部件类别(罩、门等)都对应于抽象产品。 具体部件(即99凯美瑞的司机侧门)对应 混凝土产品。

工厂方法示例:

玩具公司对应于创造者,因为它可以使用工厂来创建产品对象。制造特定类型玩具(马或汽车)的玩具公司的部门对应于ConcreteCreator。

你有一个工厂,它创建派生自特定基类的对象

抽象工厂:你有一个创建其他工厂的工厂,这些工厂反过来创建从基类派生的对象。这样做是因为您通常不只是想创建单个对象(与Factory方法一样)—相反,您想创建相关对象的集合。

查看这里:http://www.allapplabs.com/java_design_patterns/abstract_factory_pattern.htm 似乎Factory方法使用一个特定的类(不是抽象类)作为基类,而抽象工厂则使用一个抽象类。此外,如果使用接口而不是抽象类,结果将是抽象工厂模式的不同实现

: D

抽象工厂的示例/场景

我住在一个雨季下雨,冬天下雪,夏天炎热晴朗的地方。我需要不同种类的衣服来保护自己免受恶劣天气的影响。为此,我去我家附近的商店买衣服/物品来保护自己。店主根据环境和我口袋的大小给我合适的商品。他给我的商品质量和价格都是一样的。既然他知道我的标准,他就很容易这样做。但当街对面的富人提出同样的要求时,他得到的是昂贵的品牌商品。值得注意的是,他给我的所有产品在质量、标准和成本上都是互补的。可以说它们是相互配合的。这个有钱人得到的物品也是如此。

所以通过上面的场景,我现在很欣赏店主的效率。我可以用抽象商店代替这个店主。我们得到的东西是抽象的东西,而我和富人是潜在的客户。我们所需要的只是符合我们需要的产品。

现在,我可以很容易地想象自己正在考虑一家为众多客户提供一系列服务的在线商店。每个客户端属于三个组中的一个。当一个高级群组用户打开网站时,他会得到很棒的用户界面,高度定制的广告窗格,菜单中有更多的选项等。这些相同的功能集呈现给了黄金用户,但菜单中的功能较少,广告大多是相关的,UI略不符合逻辑。最后是我的用户类型,一个“自由组”用户。我得到了足够的服务,所以我不会被冒犯。UI是最低限度的,广告太偏离轨道了,以至于我不知道里面有什么,最后菜单只有注销。

如果我有机会建立一个像这样的网站,我肯定会考虑抽象工厂模式。

抽象产品:广告窗格,菜单,UI画家。
摘要工厂:Web商店用户体验
Concreate Factory:高级用户体验,黄金用户体验,普通用户体验
//Abstract factory - Provides interface to create factory of related products
interface PizzaIngredientsFactory{
public Dough createDough(); //Will return you family of Dough
public Clam createClam();   //Will return you family of Clam
public Sauce createSauce(); //Will return you family of Sauce
}


class NYPizzaIngredientsFactory implements PizzaIngredientsFactory{


@Override
public Dough createDough(){
//create the concrete dough instance that NY uses
return doughInstance;
}


//override other methods
}

课本上的定义已经由其他答案提供了。我想我也会提供一个例子。

所以这里的PizzaIngredientsFactory是一个抽象工厂,因为它提供了创建相关产品族的方法。

注意,抽象工厂中的每个方法本身都是工厂方法。就像createDough()本身是一个工厂方法,其具体实现将由NYPizzaIngredientsFactory等子类提供。因此,使用这个方法,每个不同的位置都可以创建属于其位置的具体成分实例。

工厂方法

提供具体实现的实例

示例中:
- createDough()提供面团的具体实现。这是一个工厂方法

抽象工厂

提供创建相关对象族的接口

示例中:
- PizzaIngredientsFactory是一个抽象工厂,因为它允许创建一组相关的对象,如DoughClamsSauce。对于创建每个对象族,它提供了一个工厂方法

头部优先设计模式的例子

抽象工厂是创建相关对象的接口,而工厂方法是一种方法。抽象工厂采用工厂方法实现。

enter image description here

很多人可能会感到惊讶,但这个问题是不正确的。如果你在面试中听到这个问题,你需要帮助面试官理解你的困惑在哪里。

让我们从一个事实开始,即没有具体的模式被称为“工厂”。有一种模式叫做“抽象工厂”,也有一种模式叫做“工厂方法”。

那么,“工厂”是什么意思呢?以下之一(根据引用的范围,都可以认为是正确的):

  • 有些人使用它作为“抽象工厂”的别名(快捷方式)。
  • 有些人使用它作为“工厂方法”的别名(快捷方式)。
  • 有些人将其用作所有工厂/创建模式的通用名称。例如,“抽象工厂”和“工厂方法”都是工厂。

并且,不幸的是,许多人使用“Factory”来表示另一种类型的工厂,它创建工厂或工厂(或它们的接口)。根据他们的理论:

Product实现了IProduct,它是由Factory创建的 实现了由AbstractFactory创建的IFactory

为了理解这有多愚蠢,让我们继续我们的方程:

AbstractFactory实现IAbstractFactory,它是由… AbstractAbstractFactory ? ?< / p >

我希望你能明白我的意思。不要困惑,请不要发明那些无缘无故存在的东西。

-

注::产品的工厂是AbstractFactory,而抽象工厂的工厂也只是AbstractFactory的另一个例子。

我的来源是:StackOverflowtutorialspoint.comprogrammers.stackexchange.comCodeProject.com


Factory Method(也称为Factory)用于解耦Interface实现的客户端。例如,我们有一个带有两个CircleSquare实现的Shape接口。我们已经定义了一个带有工厂方法的工厂类,该工厂方法带有一个诸如Type这样的决定符形参,以及Shape接口的新的相关实现。


Abstract Factory包含多个工厂方法或多个工厂实现的工厂接口。 对于上面的下一个示例,我们有一个带有两个RedYellow实现的Color接口。 我们已经用两个RedCircleFactoryYellowSquareFactory定义了一个ShapeColorFactory接口。下面的代码解释这个概念:

interface ShapeColorFactory
{
public Shape getShape();
public Color getColor();
}


class RedCircleFactory implements ShapeColorFactory
{
@Override
public Shape getShape() {
return new Circle();
}


@Override
public Color getColor() {
return new Red();
}
}
class YellowSquareFactory implements ShapeColorFactory
{
@Override
public Shape getShape() {
return new Square();
}


@Override
public Color getColor() {
return new Yellow();
}
}

这里是FactoryMethodAbstractFactory的区别。Factory Method返回接口的具体类,而Abstract Factory返回factory of factory。换句话说,Abstract Factory返回一系列接口的不同组合。


我希望我的解释有用。

对于John的回答,我有几点要补充如下:

抽象工厂是工厂中的工厂!

使用“Factory方法”(因为只有“Factory”是不明确的),您可以生成特定接口的实现(LemonOrange等)——比如IFruit。这个工厂可以被称为CitricFruitFactory

但是现在您想要创建CitricFruitFactory无法创建的另一种水果。如果你在CitricFruitFactory中创建一个Strawberry,也许CitricFruitFactory的代码就没有意义了(草莓不是柠檬酸水果!)。

因此,你可以创建一个名为RedFruitFactory的新Factory,它会生成StrawberryRaspberry等。

就像John Feminella说的: 使用抽象工厂模式,您可以生成特定工厂接口的实现——例如,IFruitFactory。他们每个人都知道如何创造不同种类的水果。" < / em >

IFruitFactory的实现是CitricFruitFactoryRedFruitFactory!

这些工厂的主要区别是什么时候你想用工厂做什么,什么时候你想使用它。

有时候,当你在做IOC(控制反转,例如构造函数注入)时,你知道你可以创建固体对象。正如上面水果的例子中提到的,如果你准备创建水果的对象,你可以使用简单的工厂模式

但是很多时候,你不想创建实体对象,它们会在程序流的后面出现。但是配置告诉你你想在开始时使用什么样的工厂,而不是创建对象,你可以将从公共工厂类派生的工厂传递给IOC中的构造函数。

所以,我认为这也是关于对象的生命周期和创建。

Factory MethodAbstract Factory都使客户端与具体类型解耦。两者都创建对象,但Factory方法使用继承,而Abstract Factory方法使用组合。

Factory Method继承在子类中以创建具体对象(产品),而Abstract Factory提供用于创建相关产品族的接口,这些接口的子类定义如何创建相关产品。

然后这些子类在实例化后被传递到产品类中,在产品类中它被用作抽象类型。Abstract Factory中的相关产品通常使用Factory Method实现。

基本的区别:

工厂:< em > < / em >创建对象而不向客户端公开实例化逻辑。

< em >工厂方法< / em >:定义一个创建对象的接口,但是让子类来决定实例化哪个类。Factory方法允许类延迟实例化到子类

< em >抽象工厂< / em >:提供了一个接口,用于创建相关或依赖的对象族,而不指定它们的具体类。

AbstractFactory模式使用组合将创建对象的责任委托给另一个类,而工厂方法模式使用继承并依赖于派生类或子类来创建对象

来自oodesign文章:

< >强厂< / >强类图:

enter image description here

例如:StaticFactory

 public class ShapeFactory {


//use getShape method to get object of type shape
public static Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();


} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();


} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}


return null;
}
}

非静态工厂实现FactoryMethod的例子在这篇文章中可用:

设计模式:工厂vs工厂方法vs抽象工厂

使用时间:客户端只需要一个类,并不关心它得到的具体实现。

< >强工厂方法< / >强类digaram:

enter image description here

使用时间:客户端不知道在运行时需要创建什么具体的类,但只是想获得一个将完成这项工作的类。

来自dzone< >强抽象工厂< / >强类图

enter image description here

使用时间:当你的系统必须创建多个产品家族,或者你想提供一个产品库而不暴露实现细节时。

以上文章中的源代码示例非常有助于清楚地理解这些概念。

相关SE问题与代码示例:

工厂模式。什么时候使用工厂方法?< / >

差异:

  1. 抽象工厂类通常使用工厂方法来实现,但它们也可以使用原型来实现
  2. 设计开始使用工厂方法(不太复杂,更可定制,子类激增),然后向其他需要更多灵活性的创建模式(更灵活,更复杂)发展。
  3. 工厂方法通常在模板方法中调用。

其他有用的文章:

factory_method from sourcemaking

abstract_factory from sourcemaking

abstract-factory-design-pattern from journaldev

延伸John Feminella的回答:

AppleBananaCherry实现了FruitFactory,它有一个名为Create的方法,它只负责创建Apple或Banana或Cherry。Factory方法就完成了。

现在,你想从你的水果中Create一个特殊的沙拉,这就是你的抽象工厂。抽象工厂知道如何用苹果、香蕉和樱桃制作你的特殊沙拉。

public class Apple implements Fruit, FruitFactory {
public Fruit Create() {
// Apple creation logic goes here
}
}


public class Banana implements Fruit, FruitFactory {
public Fruit Create() {
// Banana creation logic goes here
}
}


public class Cherry implements Fruit, FruitFactory {
public Fruit Create() {
// Cherry creation logic goes here
}
}


public class SpecialSalad implements Salad, SaladFactory {
public static Salad Create(FruitFactory[] fruits) {
// loop through the factory and create the fruits.
// then you're ready to cut and slice your fruits
// to create your special salad.
}
}

抽象工厂是创建不同类型接口的模板。 假设你有一个项目,需要你解析不同类型的csv文件,价格和特定项目的信息,比如一些包含水果的数据,其他关于巧克力,然后在解析后,你需要在相应的数据库中更新这些信息,所以现在你可以有一个抽象工厂返回你的解析器和修饰器工厂,然后这个解析器工厂可以返回你巧克力解析器对象,水果解析器对象等,类似的修饰器工厂可以返回巧克力修饰器对象,水果修饰器对象等

根据定义,我们可以拖出两者的差异:

工厂:接口用于创建对象,但子类决定实例化哪个类。对象的创建是在需要时完成的。

抽象工厂:抽象工厂模式充当一个超级工厂,它可以创建其他工厂。在抽象工厂模式中,接口负责创建一组相关对象或依赖对象,而不指定它们的具体类。

所以,在上面的定义中,我们可以强调一个特定的区别。也就是说,工厂模式负责创建对象,抽象工厂负责创建一组相关的对象;显然都是通过一个接口。

工厂模式:

public interface IFactory{
void VehicleType(string n);
}


public class Scooter : IFactory{
public void VehicleType(string n){
Console.WriteLine("Vehicle type: " + n);
}
}


public class Bike : IFactory{
public void VehicleType(string n) {
Console.WriteLine("Vehicle type: " + n);
}
}


public interface IVehicleFactory{
IFactory GetVehicleType(string Vehicle);
}


public class ConcreteVehicleFactory : IVehicleFactory{
public IFactory GetVehicleType(string Vehicle){
switch (Vehicle){
case "Scooter":
return new Scooter();
case "Bike":
return new Bike();
default:
return new Scooter();
}
}


class Program{
static void Main(string[] args){
IVehicleFactory factory = new ConcreteVehicleFactory();
IFactory scooter = factory.GetVehicleType("Scooter");
scooter.VehicleType("Scooter");


IFactory bike = factory.GetVehicleType("Bike");
bike.VehicleType("Bike");


Console.ReadKey();
}
}

工厂模式:

interface IVehicleFactory{
IBike GetBike();
IScooter GetScooter();
}


class HondaFactory : IVehicleFactory{
public IBike GetBike(){
return new FZS();
}
public IScooter GetScooter(){
return new FZscooter();
}
}
class HeroFactory: IVehicleFactory{
public IBike GetBike(){
return new Pulsur();
}
public IScooter GetScooter(){
return new PulsurScooter();
}
}


interface IBike
{
string Name();
}
interface IScooter
{
string Name();
}


class FZS:IBike{
public string Name(){
return "FZS";
}
}
class Pulsur:IBike{
public string Name(){
return "Pulsur";
}
}


class FZscooter:IScooter {
public string Name(){
return "FZscooter";
}
}


class PulsurScooter:IScooter{
public string Name(){
return "PulsurScooter";
}
}


enum MANUFACTURERS
{
HONDA,
HERO
}


class VehicleTypeCheck{
IBike bike;
IScooter scooter;
IVehicleFactory factory;
MANUFACTURERS manu;


public VehicleTypeCheck(MANUFACTURERS m){
manu = m;
}


public void CheckProducts()
{
switch (manu){
case MANUFACTURERS.HONDA:
factory = new HondaFactory();
break;
case MANUFACTURERS.HERO:
factory = new HeroFactory();
break;
}


Console.WriteLine("Bike: " + factory.GetBike().Name() + "\nScooter: " +      factory.GetScooter().Name());
}
}


class Program
{
static void Main(string[] args)
{
VehicleTypeCheck chk = new VehicleTypeCheck(MANUFACTURERS.HONDA);
chk.CheckProducts();


chk= new VehicleTypeCheck(MANUFACTURERS.HERO);
chk.CheckProducts();


Console.Read();
}
}

我认为我们可以通过查看Java8示例代码来理解这两者之间的区别:

  interface Something{}


interface OneWhoCanProvideSomething {
Something getSomething();
}


interface OneWhoCanProvideCreatorsOfSomething{
OneWhoCanProvideSomething getCreator();
}




public class AbstractFactoryExample {


public static void main(String[] args) {
//I need something
//Let's create one
Something something = new Something() {};


//Or ask someone (FACTORY pattern)
OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeA = () -> null;
OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeB = () -> null;


//Or ask someone who knows soemone who can create something (ABSTRACT FACTORY pattern)
OneWhoCanProvideCreatorsOfSomething oneWhoCanProvideCreatorsOfSomething = () -> null;


//Same thing, but you don't need to write you own interfaces
Supplier<Something> supplierOfSomething = () -> null;
Supplier<Supplier<Something>> supplierOfSupplier = () -> null;
}


}
现在的问题是你应该使用哪种创建方式以及为什么: 第一种方式(没有模式,只是普通的构造函数):自己创建不是一个好主意,你必须做所有的工作,你的客户端代码是绑定到特定的实现

第二种方式(使用Factory模式):为您提供了可以传递任何类型的实现的好处,这些实现可以基于某些条件(可能是传递给创建方法的参数)提供不同类型的东西。

第三种方法(使用抽象工厂模式):这为您提供了更多的灵活性。您可以根据某些条件(可能是传递的参数)找到不同类型的创建者。

请注意,你总是可以通过将两个条件结合在一起来摆脱工厂模式(这稍微增加了代码的复杂性和耦合性),我想这就是为什么我们很少看到抽象工厂模式的现实用例