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

What is the basic difference between the Factory and Abstract Factory Patterns?

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


使用工厂模式,可以生成特定接口的实现实例(AppleBananaCherry等,例如IFruit

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


Source for this information taken from: http://java.dzone.com/news/intro-design-patterns-abstract

抽象工厂与工厂方法

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

抽象工厂模式由抽象工厂、具体工厂、抽象产品、具体产品和客户组成。

如何实施

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

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

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

何时使用工厂方法模式

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

何时使用抽象工厂模式

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

实例:抽象工厂示例1

本规范适用于制备不同类型面食的圆盘在面食制造机中是抽象工厂,每个特定的磁盘都是工厂。所有工厂(Pasta Maker磁盘)都从抽象工厂继承其属性。每个单独的磁盘都包含如何创建面食的信息,而面食制造商没有。

抽象工厂示例2:

冲压设备与抽象工厂相对应,因为它是一个用于创建抽象产品对象的操作的接口。模具与混凝土工厂相对应,因为它们可以生产混凝土产品。每个零件类别(机罩、门等)对应于抽象产品。特定零件(即99凯美瑞的驾驶员侧门)对应于混凝土产品。

工厂方法示例:

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


工厂模式:工厂生产IProduct实现

抽象工厂模式:一家工厂生产工厂,反过来生产我的产品。

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


抽象工厂模式

  • 提供用于创建的接口亲属或家属不指定对象的混凝土等级。

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

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

工厂模式

  • 工厂模式是生成模式

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

  • 阶级创造模式集中于使用继承来决定要实例化的对象工厂法

  • 对象创造模式专注于实例化的委托到另一个对象抽象工厂

参考文献:工厂与抽象工厂


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

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


抽象工厂接口for creating is an method is but工厂相关的对象的方法。要实现抽象工厂模式,工厂方法。P></

enter image description hereP></


基本区别:

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

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

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

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

来自oodesign文章:

工厂类图:

enter image description here

示例:StaticFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 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问题:

工厂模式。何时使用工厂方法?

差异:

  • 抽象工厂类通常使用工厂方法实现,但也可以使用原型实现
  • 设计从使用工厂方法开始(不那么复杂,更可定制,子类激增),并发展到需要更多灵活性的其他创造模式(更灵活,更复杂)。
  • 工厂方法通常在模板方法中调用。
  • 其他有用文章:

    来源制作的工厂方法

    从源代码中提取工厂

    从JournalDev中抽象工厂设计模式


    抽象工厂/情景for exampleP></

    在现场的地方它下雨下雨snows茶季,冬季和夏季热,阳光。需要保护自己的衣服kind of different from the元素。我知道我对我的房子和商店近to the items to ask for服饰/保护自己。茶叶店管理员给我适当的As the item of the环境和对我的口袋深度。他给我的是the items of same level of品质和价格范围。因为他是我的标准很容易感知of its to给他知道。but when丰富的家伙在街上,从他得到安with the same’的要求,TP item。在一个noticeable thing is the items to each other我给他补的质量标准在长期,和成本。他们可以去一个说with each other。is the same with the items这家伙的房子变得丰富。P></

    我看着上面的情景模式,现在appreciate the efficiency of the店管理员。我shopkeeper replace this with an摘要店。摘要我们get with the items and the rich as items和我clients视角。我们need is the item which needs我们的产品/服。P></

    现在我可以看到我自己easily安在线商店提供considering which to its of a numerous clients服务集。客户端belongs to each one of the three groups。当用户在网站上的优质茶叶集团opens辐射得到高度customised广告大IU,面包,茶menus黑莓期权等。这些特点是同集of the user to金给我在the is less菜单功能性角度分析,是slightly less是相关的,和egronomic IU。last is My kind of user组用户,是免费的。我只知道我已经served offended Do not get。IU is the minimum棺材是离线方式,多角度分析跟踪我,我知道它是在Do not,has only the菜单lastly注销。P></

    如果get something to build的机会当然会考虑这样的网站抽象工厂模式。P></

    摘要:面包产品广告,菜单,IU的画家。抽象工厂:网站用户体验店具体工厂的高级用户:用户体验,用户体验的黄金,一般的经验。P></


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

    让我们从没有所谓的"工厂"的具体模式开始。有一种模式称为"抽象工厂",还有一种模式称为"工厂方法"。

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

    • 有些人把它用作"抽象工厂"的别名(快捷方式)。
    • 有些人把它用作"工厂方法"的别名(快捷方式)。
    • 有些人把它作为所有工厂/创造模式的通用名称。例如,"抽象工厂"和"工厂方法"都是工厂。

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

    Product implements IProduct, which is created by Factory, which
    implements IFactory, which is created by AbstractFactory.

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

    AbstractFactory implements IAbstractFactory, which is created by...
    AbstractAbstractFactory???

    我希望你明白这一点。不要困惑,也不要发明那些不存在的东西。

    -

    P.S.:产品的工厂是抽象工厂,抽象工厂的工厂也是抽象工厂的另一个例子。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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
    }

    the text by other are already书提供详细的定义。我的思想太an example of恩提供。P></

    我在这里PizzaIngredientsFactoryis an as the抽象工厂方法创建的家庭提供IT相关产品的杂志。P></

    注意each that is the method在抽象工厂方法工厂安在本身。类本身是在createDough()工厂方法模式的具体implementations谁提供subclasses NYPizzaIngredientsFactorywill be like。我知道这可以创建使用不同位置的情况下,each of that to their ingredients属于具体位置。P></工厂方法

    Provides instance of concrete implementation

    在the example:我createDough()-提供具体执行for面团。我知道this method is a工厂P></抽象工厂

    Provides interface to create family of related objects

    在the example:摘要:PizzaIngredientsFactoryis as an en to create a allows工厂类的对象集Dough相关学院,ClamsSauce。for each of creating家庭/工厂对象提供方法。P></

    example from head first设计模式P></


    我对约翰的回答有以下几点看法:

    抽象工厂是工厂的工厂!

    使用"工厂方法"(因为"工厂"不明确),可以生成特定接口的实现(LemonOrange等),例如IFruit。这个工厂可以称为CitricFruitFactory

    但是现在你要创造出另一种柠檬水果工厂无法创造的水果。如果你在其中创建一个Strawberry,那么CitricFruitFactory的代码可能就没有意义了(草莓不是柠檬水果!).

    所以你可以创建一个新的工厂,叫做RedFruitFactory,生产StrawberryRaspberry等。

    就像约翰·费米内拉说的:"使用抽象工厂模式,可以生成特定工厂接口的实现——例如,IFruitFactory。每个人都知道如何制作不同种类的水果。"

    实施IFruitFactory的是CitricFruitFactoryRedFruitFactory


    这些工厂的主要区别在于你想在什么时候处理这些工厂以及你想在什么时候使用它们。

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

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

    所以,我认为它也与物体的寿命和创造有关。


    延伸约翰·费米内拉的回答:

    AppleBananaCherry实现FruitFactory,其方法称为Create,专门负责制作苹果、香蕉或樱桃。你用你的Factory方法完成了。

    现在,你想从水果中提取一种特殊的色拉,抽象工厂就来了。抽象工厂知道如何用苹果、香蕉和樱桃制作你的特色沙拉。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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.
        }
    }

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

    Factory Method(也称为Factory)用于实现Interface的分离客户机。对于示例,我们有一个与两个CircleSquare实现的Shape接口。我们用一个工厂方法定义了一个工厂类,这个工厂方法有一个确定的参数,比如TypeShape接口的新的相关实现。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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返回一系列接口的不同组合。

    我希望我的解释有用。


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

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

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


    根据定义,我们可以将以下两个方面的差异拉出来:

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

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

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

    工厂模式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    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();
     }
    }

    抽象工厂模式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    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() +"
    Scooter:" +      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示例代码来理解这两者之间的区别:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
      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;
        }

    }

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

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

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

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


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

    D


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