510

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

4

19 回答 19

430

使用工厂模式,您可以生成Apple特定接口(Banana例如.CherryIFruit

使用抽象工厂模式,您可以为任何人提供一种方式来提供自己的工厂。这使您的仓库可以是 anIFruitFactory或 an IJuiceFactory,而无需您的仓库了解有关水果或果汁的任何信息。

于 2009-06-16T14:18:25.683 回答
149

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

抽象工厂与工厂方法

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

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

如何实施

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

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

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

何时使用工厂方法模式

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

何时使用抽象工厂模式

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

例子:

抽象工厂示例 1

用于在意大利面制造商中准备不同类型意大利面的磁盘的规范是抽象工厂,每个特定的磁盘都是一个工厂。所有工厂(意大利面制造商磁盘)都从抽象工厂继承其属性。每个单独的磁盘都包含如何制作意大利面的信息,而意大利面制造商没有。

抽象工厂示例 2:

冲压设备对应于抽象工厂,因为它是创建抽象产品对象的操作的接口。模具对应于混凝土工厂,因为它们制造了混凝土产品。每个零件类别(引擎盖、门等)对应于抽象产品。具体部件(即99凯美瑞驾驶员侧车门)对应具体产品。

工厂方法示例:

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

于 2010-04-13T18:20:59.773 回答
102

工厂模式:工厂生产IProduct-实施

抽象工厂模式:工厂工厂生产 IFactories,而后者又生产 IProducts :)

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

于 2009-06-16T14:16:41.473 回答
44

抽象工厂模式

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

  • 抽象工厂模式与工厂方法模式非常相似。两者之间的一个区别在于,对于抽象工厂模式,一个类通过组合将对象实例化的责任委托给另一个对象,而工厂方法模式使用继承并依赖子类来处理所需的对象实例化。

  • 实际上,委托对象经常使用工厂方法来执行实例化!

工厂模式

  • 工厂模式是创建模式的示例

  • 创建模式抽象了对象实例化过程。它们隐藏了对象的创建方式,并有助于使整个系统独立于其对象的创建和组合方式。

  • 类创建模式侧重于使用继承来决定要实例化的对象工厂方法

  • 对象创建模式专注于将实例化委托给另一个对象抽象工厂

参考: 工厂与抽象工厂

于 2009-06-16T14:16:18.260 回答
41

工厂方法:您有一个工厂,它创建从特定基类派生的对象

抽象工厂:您有一个创建其他工厂的工厂,而这些工厂又创建从基类派生的对象。这样做是因为您通常不只是想创建单个对象(如使用 Factory 方法),而是希望创建相关对象的集合。

于 2011-05-06T07:10:24.570 回答
39

基本区别:

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

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

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

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

来自oodesign文章:

工厂类图:

在此处输入图像描述

示例:静态工厂

 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 抽象工厂

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

工厂方法类图表:

在此处输入图像描述

何时使用:客户端不知道在运行时需要创建哪些具体类,但只想获得一个可以完成这项工作的类。

来自dzone的抽象工厂类图

在此处输入图像描述

何时使用:当您的系统必须创建多个产品系列或您想要提供产品库而不公开实现细节时。

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

带有代码示例的相关 SE 问题:

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

差异:

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

其他有用的文章:

来自sourcemaking的 factory_method

来自 sourcemaking 的abstract_factory

来自 journaldev的抽象工厂设计模式

于 2016-03-01T04:24:45.840 回答
36

抽象工厂是用于创建相关对象的接口,但工厂方法是一种方法。抽象工厂是通过工厂方法实现的。

在此处输入图像描述

于 2013-12-18T02:17:58.403 回答
24

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

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

那么,“工厂”是什么意思呢?以下之一(所有都可以被认为是正确的,取决于参考的范围):

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

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

Product 实现了由 Factory 创建的 IProduct,后者实现了由 AbstractFactory 创建的 IFactory。

为了理解这是多么愚蠢,让我们继续我们的等式:

AbstractFactory 实现了 IAbstractFactory,它是由...AbstractAbstractFactory 创建的?

我希望你明白这一点。不要迷惑​​,也请不要发明不存在的东西。

-

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

于 2014-12-19T18:54:41.243 回答
23

抽象工厂的示例/场景

我住在一个雨季下雨,冬天下雪,夏天炎热和阳光充足的地方。我需要不同种类的衣服来保护自己免受元素的伤害。为此,我会去我家附近的商店买衣服/物品来保护自己。店员会根据我口袋的环境和深度给我合适的物品。他给我的物品质量和价格范围相同。因为他知道我的标准,所以他很容易这样做。但是,当街对面的一个有钱人提出同样的要求时,他会得到一件昂贵的品牌商品。一件值得注意的事情是,他给我的所有物品在质量、标准和成本方面都相得益彰。可以说他们是一起去的。这个有钱人得到的物品也是如此。

所以通过看上面的场景,我现在很欣赏店主的效率。我可以用抽象商店代替这个店主。我们得到的项目是抽象项目,我和富人作为透视客户。我们所需要的只是适合我们需求的产品/项目。

现在我可以很容易地看到自己正在考虑为众多客户提供一系列服务的在线商店。每个客户都属于三个组之一。当高级组用户打开网站时,他会获得出色的用户界面、高度定制的广告窗格、菜单中的更多选项等。这些相同的功能集呈现给黄金用户,但菜单中的功能较少,广告大多是相关的,和稍微少一点的人机界面。最后是我的一种用户,一个“免费组”用户。我只是得到足够的服务,所以我不会被冒犯。用户界面是最低限度的,广告太离谱了,以至于我不知道里面有什么,最后菜单只有注销。

如果我有机会建立类似这个网站的东西,我肯定会考虑抽象工厂模式。

抽象产品:广告窗格、菜单、UI 画家。
抽象工厂:网店用户体验
Concreate Factory:高级用户体验、金牌用户体验、一般用户体验。

于 2012-10-20T06:02:25.677 回答
17
//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是一个抽象工厂,因为它提供了创建相关产品系列的方法。

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

工厂方法

提供具体实现的实例

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

抽象工厂

提供创建相关对象系列的接口

在示例中:
-PizzaIngredientsFactory是一个抽象工厂,因为它允许创建一组相关的对象,例如Dough, Clams, Sauce。为了创建每个对象系列,它提供了一个工厂方法。

Head First 设计模式的示例

于 2013-08-09T06:48:23.040 回答
5

我对约翰的回答有一些贡献,如下所示:

抽象工厂是工厂的工厂!

使用“工厂方法”(因为只是“工厂”是模棱两可的),您可以生成特定接口的实现( 、 等)——Lemon比如. 这个工厂可以被称为。OrangeIFruitCitricFruitFactory

但是现在您想要创建 CitricFruitFactory 无法创建的另一种水果。如果您在其中创建一个,则代码CitricFruitFactory可能没有意义Strawberry(草莓不是柠檬水果!)。

所以你可以创建一个新的 FactoryRedFruitFactory来生产Strawberry,Raspberry等等。

正如 John Feminella 所说: “使用抽象工厂模式,您可以生成特定工厂接口的实现——例如,IFruitFactory。每个人都知道如何创建不同种类的水果。”

IFruitFactoryareCitricFruitFactoryRedFruitFactory!的实现

于 2015-10-21T20:25:29.793 回答
4

我的来源是:StackOverflow、、 tutorialspoint.com和。programmers.stackexchange.comCodeProject.com


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


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

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();
    }
} 

FactoryMethod这里和之间的区别AbstractFactoryFactory Method就像简单地返回一个具体的接口类但Abstract Factoryreturn factory of factory。也就是说Abstract Factory返回一系列接口的不同组合。


我希望我的解释有用。

于 2015-06-02T15:04:51.273 回答
3

这些工厂的主要区别在于您何时想对工厂做什么以及何时想使用它。

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

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

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

于 2016-01-06T21:11:01.647 回答
3

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

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

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

于 2016-01-17T08:51:27.027 回答
3

扩展 John Feminella 的答案:

Apple, Banana,Cherry实现FruitFactory并且有一个方法被调用Create,该方法单独负责创建 Apple 或 Banana 或 Cherry。你用你的Factory方法完成了。

现在,你想用Create你的水果做一份特别的沙拉,你的抽象工厂来了。Abstract Factory 知道如何用苹果、香蕉和樱桃制作您的特色沙拉。

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.
    }
}
于 2016-10-26T11:57:00.350 回答
2

通过定义我们可以拖出两者的区别:

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

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

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

工厂模式:

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();
        }
    }
于 2017-02-15T10:48:00.070 回答
1

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

:D

于 2012-01-06T15:15:08.003 回答
1

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

于 2016-12-25T09:27:38.957 回答
1

我想我们可以通过查看 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;
    }

}

现在的问题是您应该使用哪种创建方式以及为什么:第一种方式(没有模式,只是简单的构造函数):自己创建不是一个好主意,您必须完成所有工作,并且您的客户端代码与具体实现。

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

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

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

于 2017-04-25T06:09:03.720 回答