代码之家  ›  专栏  ›  技术社区  ›  user366312

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

  •  455
  • user366312  · 技术社区  · 16 年前

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

    19 回复  |  直到 16 年前
        1
  •  392
  •   John Feminella    7 年前

    使用工厂模式,可以生成实现的实例( Apple , Banana , Cherry 等)一个特定的接口——比如, IFruit .

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

        2
  •  139
  •   Jimbo Paul Stanley    11 年前

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

    抽象工厂与工厂方法

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

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

    如何实施

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

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

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

    何时使用工厂方法模式

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

    何时使用抽象工厂模式

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

    实例:

    抽象工厂示例1

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

    抽象工厂示例2:

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

    工厂方法示例:

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

        3
  •  95
  •   cwap    8 年前

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

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

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

        4
  •  42
  •   Richard JP Le Guen    12 年前

    抽象工厂模式

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

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

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

    工厂模式

    • 工厂模式是 生成模式

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

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

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

    参考文献: Factory vs Abstract Factory

        5
  •  38
  •   Craig Schwarze    14 年前

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

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

        6
  •  36
  •   Trying    11 年前

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

    enter image description here

        7
  •  32
  •   Ravindra babu    8 年前

    基本区别:

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

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

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

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

    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 DigaRAM类:

    enter image description here

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

    Abstract Factory 类图来自 dzone

    enter image description here

    何时使用: 当您的系统必须创建多个产品系列,或者您希望在不公开实现细节的情况下提供产品库时。

    上面文章中的源代码示例对于清楚理解这些概念非常好。

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

    Factory Pattern. When to use factory methods?

    差异:

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

    其他有用文章:

    factory_method 源代码生成

    abstract_factory 源代码生成

    abstract-factory-design-pattern 从日记

        8
  •  21
  •   ataulm    9 年前

    抽象工厂的示例/场景

    我住在一个雨季下雨,冬天下雪,夏天又热又晴的地方。我需要不同种类的衣服来保护自己不受天气的影响。为了做到这一点,我去了我家附近的商店,要衣服/物品来保护自己。店主根据我的环境和口袋的深度给了我合适的物品。他给我的东西质量和价格都是一样的。因为他知道我的标准,所以他很容易做到。但当街对面的一个有钱人提出同样的要求时,他就会得到一件昂贵的名牌产品。一个值得注意的是,他给我的所有东西在质量、标准和成本上都是相辅相成的。我们可以说他们是一起去的。这个有钱人得到的东西也是如此。

    因此,通过以上的场景,我现在感激店主的效率。我可以用抽象的商店代替这个店主。我们从抽象项目中得到的项目,以及作为透视客户的我和富人。我们所需要的是适合我们需要的产品/项目。

    现在我可以很容易地看到自己正在考虑一个在线商店,它为众多客户提供一套服务。每个客户机属于三个组中的一个。当高级组用户打开站点时,他会得到很棒的用户界面、高度定制的广告窗格、菜单中的更多选项等。这些相同的功能集将呈现给黄金用户,但菜单中的功能较少,广告主要是相关的,而经济的用户界面则略少。最后一个是我的用户类型,一个自由组用户。我只是得到了足够的服务,这样我就不会被冒犯了。用户界面是最低限度的,广告太离谱了,我不知道里面有什么,最后菜单只有注销。

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

    抽象产品:广告窗格,菜单,用户界面绘制。
    抽象工厂:网络商店用户体验
    ConCreate工厂:高级用户体验、黄金用户体验、一般用户体验。

        9
  •  18
  •   Tengiz    10 年前

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

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

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

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

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

    产品实现由工厂创建的iproduct,其中 实现由AbstractFactory创建的iFactory。

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

    AbstractFactory实现了IABStractFactory,它是由… 抽象工厂????

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

    -

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

        10
  •  15
  •   Narendra Pathai    12 年前
    //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 .因此,使用这个位置,每个不同的位置都可以创建属于其位置的具体成分的实例。

    工厂法

    提供具体实现的实例

    在例子中:
    - 创建() -提供面团的具体实现。所以这是工厂方法

    抽象工厂

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

    在例子中:
    - 比萨食品厂 是一个抽象工厂,因为它允许创建一组相关的对象,如 Dough , Clams , Sauce . 对于创建每个对象族,它提供了一个工厂方法。

    例子来自 Head First design patterns

        11
  •  5
  •   fabriciorissetto    9 年前

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

    抽象工厂是工厂的工厂!

    使用“工厂方法”(因为“工厂”不明确),您将生成实现( Lemon , Orange 等)一个特定的接口——比如, IFruit . 这个工厂可以叫 CitricFruitFactory .

    但是现在你要创造出另一种柠檬水果工厂无法创造的水果。也许是代码 柠檬水果厂 如果你创建一个 Strawberry 在里面(草莓不是柠檬水果!).

    所以你可以创建一个新的工厂 RedFruitFactory 产生 草莓 , Raspberry 等。

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

    实现 炼厂 柠檬水果厂 红果厂 !

        12
  •  3
  •   Mahendra Vengurlekar    9 年前

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

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

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

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

        13
  •  3
  •   Abdul Munim    8 年前

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

    Apple , Banana , Cherry 器具 FruitFactory 还有一个方法 Create 它完全负责苹果、香蕉或樱桃的制作。你完成了,你的 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.
        }
    }
    
        14
  •  3
  •   LC 웃    7 年前

    我的资料来源是: StackOverflow , tutorialspoint.com , programmers.stackexchange.com CodeProject.com .


    Factory Method (也称为 Factory )是用于 Interface 实施。对于样品,我们有一个 Shape 与两个接口 Circle Square 实施。我们已经用带有限定参数的工厂方法定义了工厂类,例如 Type 以及新的相关实施 形状 接口。


    Abstract Factory 包含多个工厂方法或由多个工厂实现的工厂接口。 对于上面的下一个示例,我们有一个 Color 与两个接口 Red Yellow 实施。 我们已经定义了 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 AbstractFactory . 工厂法 只是返回一个接口的具体类,但是 抽象工厂 返回 factory of factory . 换言之 抽象工厂 返回一系列接口的不同组合。


    我希望我的解释有用。

        15
  •  2
  •   Alexei - check Codidact    9 年前

    两个 Factory Method Abstract Factory 使客户机与具体类型分离。两者都创建对象,但 Factory 方法使用继承,而 抽象工厂 使用合成。

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

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

        16
  •  2
  •   Rashedul.Rubel    8 年前

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

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

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

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

    工厂模式:

    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();
            }
        }
    
        17
  •  1
  •   hackus    13 年前

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

    D

        18
  •  1
  •   PapaDiHatti    8 年前

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

        19
  •  1
  •   Satyendra Kumar    8 年前

    我认为我们可以通过看到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;
        }
    
    }
    

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

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

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

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

    推荐文章