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

时间:2009-06-16 14:14:07

标签: design-patterns factory abstract-factory factory-method

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

19 个答案:

答案 0 :(得分:396)

使用Factory模式,您可以生成特定接口(例如Apple)的实现实例(BananaCherryIFruit等)。 / p>

使用抽象工厂模式,您可以为任何人提供自己的工厂。这使您的仓库可以是IFruitFactoryIJuiceFactory,而无需仓库了解水果或果汁。

答案 1 :(得分:140)

  

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

抽象工厂与工厂方法

抽象工厂的方法是作为工厂方法实现的。抽象工厂模式和工厂方法模式都通过抽象类型和工厂将客户端系统与实际实现类分离。 Factory方法通过继承创建对象,其中Abstract Factory通过合成创建对象。

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

如何实施

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

Factory Method模式是Abstract Factory模式的简化版本。 Factory Method模式负责创建属于一个系列的产品,而Abstract Factory模式负责处理多个产品系列。

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

何时使用工厂方法模式

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

何时使用抽象工厂模式

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

示例:

抽象工厂示例1

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

抽象工厂示例2:

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

工厂方法示例:

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

答案 2 :(得分:97)

工厂模式: 工厂生产IProduct-implementation

抽象工厂模式: 工厂 - 工厂生产IFactories,然后生产IP产品:)

[根据评论更新]
根据{{​​3}}至少,我之前写的内容并不正确。抽象工厂只是一个工厂界面。有了它,您可以在运行时切换工厂,以允许不同的工厂在不同的环境中。示例可以是针对不同操作系统,SQL提供程序,中间件驱动程序等的不同工厂。

答案 3 :(得分:42)

抽象工厂模式

  • 提供创建界面 相关或依赖的家庭 没有指定它们的对象 具体课程。

  • 抽象工厂模式非常 类似于工厂方法 图案。一个区别 二是与抽象工厂 模式,一个类委托 对象的责任 通过实例化到另一个对象 组成而工厂 方法模式使用继承和 依赖于子类来处理 期望的对象实例化。

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

工厂模式

  • 工厂模式就是例子 创作模式

  • 创作模式抽象出来 对象实例化过程。他们 隐藏对象的创建方式和帮助 使整个系统独立 它的对象是如何创建的 组成

  • 课堂创作模式的重点是 使用继承来决定 要实例化的对象 工厂方法

  • 对象创作模式的重点是 实例化的代表团 到另一个对象 抽象工厂

参考: Factory vs Abstract Factory

答案 4 :(得分:38)

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

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

答案 5 :(得分:37)

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

enter image description here

答案 6 :(得分:34)

基本差异:

工厂: 创建对象而不将实例化逻辑暴露给客户端。

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

抽象工厂 :提供用于创建相关或从属对象族的接口,而无需指定其具体类。

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

来自oodesign文章:

Factory类图:

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示例的非静态工厂:

Design Patterns: Factory vs Factory method vs Abstract Factory

何时使用:客户端只需要一个类,而不关心它正在实现哪个具体实现。

Factory Method class digaram:

enter image description here

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

来自Abstract Factory

dzone类图

enter image description here

何时使用:当您的系统必须创建多个产品系列,或者您希望提供产品库而不暴露实施细节时。

上述文章中的源代码示例非常适合清楚地理解这些概念。

与代码示例相关的SE问题:

Factory Pattern. When to use factory methods?

<强>差异:

  1. 抽象工厂类通常使用工厂方法实现,但也可以使用Prototype
  2. 实现
  3. 设计开始使用工厂方法(不太复杂,可定制,子类增加),并朝着其他需要更多灵活性的创建模式(更灵活,更复杂)发展。
  4. 工厂方法通常在模板方法中调用。
  5. 其他有用的文章:

    来自sourcemaking的

    factory_method

    来自sourcemaking的

    abstract_factory

    来自journaldev的

    abstract-factory-design-pattern

答案 7 :(得分:21)

抽象工厂的示例/场景

我住在雨季下雨的地方,冬天下雪,夏天炎热,阳光充足。我需要不同种类的衣服来保护自己免受这些因素的影响。为此,我去了我家附近的商店,要求衣服/物品来保护自己。店主根据口袋的环境和深度给我合适的物品。他给我的物品质量和价格范围相同。由于他了解我的标准,因此他很容易这样做。但是,当街对面的富人提出相同的要求时,他会获得一件昂贵的品牌商品。一个值得注意的事情是他给我的所有项目在术语质量,标准和成本方面相互补充。可以说他们互相帮助。这个有钱人得到的物品也是如此。

因此,通过观察上述情况,我现在感谢店主的效率。我可以用抽象商店取代这个店主。我们通过抽象项目和我以及富人作为透视客户获得的项目。我们所需要的只是符合我们需求的产品/项目。

现在,我可以很容易地看到自己正在考虑一个为众多客户提供一系列服务的在线商店。每个客户都属于三个组中的一个。当高级组用户打开网站时,他获得了很棒的UI,高度定制的广告窗格,菜单中的更多选项等。这些相同的功能集呈现给黄金用户,但菜单中的功能较少,广告大多是相关的,并且略微减少了egronomic UI。最后是我的用户,一个“免费组”用户。我的服务足够让我不被冒犯。 UI是最低限度的,广告偏离轨道太多,以至于我不知道它的内容,最后菜单只有注销。

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

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

答案 8 :(得分:19)

许多人可能会感到惊讶,但这个问题不正确。如果你在面试中听到这个问题,你需要帮助面试官了解混乱的地方。

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

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

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

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

  

产品实现了由Factory创建的IProduct   实现IFactory,它由AbstractFactory创建。

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

  

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

我希望你明白这一点。不要混淆,请不要发明那些不合理的东西。

-

P.S。:Factory for Products是AbstractFactory,而Factory for Abstract Factories也只是AbstractFactory的另一个例子。

答案 9 :(得分:16)

//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是一个抽象工厂,因为它提供了创建相关产品系列的方法。

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

工厂方法

  

提供具体实施的实例

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

抽象工厂

  

提供创建相关对象族的界面

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

来自Head First design patterns

的示例

答案 10 :(得分:5)

我有一些观点可以用John的答案作出如下贡献:

抽象工厂是工厂的工厂!

使用“工厂方法”(因为只是“工厂”不明确),您可以生成特定接口的实现(LemonOrange等) - 例如{{1} }。可以将此工厂称为IFruit

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

因此,您可以创建一个名为Strawberry的新工厂,生成RedFruitFactoryStrawberry等。

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

IFruitFactory的实施是IFruitFactoryCitricFruitFactory

答案 11 :(得分:3)

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

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

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

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返回一系列界面的不同组合。

我希望我的解释很有用。

答案 12 :(得分:3)

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

有时候,在进行IOC(控制反转,例如构造函数注入)时,您知道可以创建实体对象。如上面的水果示例中所述,如果您准备创建水果对象,则可以使用简单的工厂模式

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

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

答案 13 :(得分:3)

延伸John Feminella回答:

AppleBananaCherry实现了FruitFactory,并且有一个名为Create的方法,它独自负责创建Apple或Banana或Cherry。您已完成,使用Factory方法。

现在,你想从你的水果中Create特别的沙拉,然后你的抽象工厂。 Abstract Factory知道如何用Apple,Banana和Cherry创建特殊的沙拉。

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.
    }
}

答案 14 :(得分:2)

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

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

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

答案 15 :(得分:2)

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

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

抽象工厂:抽象工厂模式作为一个超级工厂,创造其他工厂。在抽象工厂模式中,接口负责创建一组相关对象或从属对象,而不指定其具体类。

因此,在上面的定义中,我们可以强调一个特定的差异。也就是说,Factory模式负责创建对象,而Abstract Factory负责创建一组相关对象;显然都是通过界面。

工厂模式:

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

答案 16 :(得分:1)

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

:d

答案 17 :(得分:1)

Abstract Factory是用于创建不同类型接口的模板。 假设您有项目要求您解析包含数量,价格和项目特定信息的不同类型的csv文件,例如某些包含有关巧克力的水果数据,然后解析后需要在相应的数据库中更新此信息,这样您就可以拥有一个抽象工厂返回你的解析器和修改器工厂然后这个解析器工厂可以返回巧克力解析器对象,Fruit Parser Object等,类似的Modifier Factory可以返回Chocolate修饰符对象,Fruit Modifier对象等。

答案 18 :(得分: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;
    }

}

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

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

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

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