首页 文章

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

提问于
浏览
139

注意:问题在帖子的末尾 .

我已经阅读了有关 Abstract Factory vs Factory Method 的其他stackoverflow线程 . 我理解每个模式的意图 . 但是,我不清楚这个定义 .

Factory Method定义用于创建对象的接口,但是让子类决定实例化哪些接口 . 工厂方法允许类将实例化延迟到子类 . 相比之下,抽象工厂提供了一个接口,用于创建相关或依赖对象的族,而无需指定其具体类 .

Abstract Factory 看起来与 Factory Method 非常相似 . 我已经绘制了一些UML类来说明我的观点 .

注意:

  • 该图来自www.yuml.com,因此它们并不是完美导向的 . 但它的免费服务:) .

  • 图表可能不完美 . 我还在学习 GoF 设计模式 .

Factory Method:

Factory Method

Abstract Factory (only 1 member):

Abstract Factory (only 1 member)

Abstract Factory (more members):

alt text

Questions:

  • 如果 Abstract Factory 只有一个创作者和一个产品,它仍然是 Abstract Factory 模式吗? (创建家庭的界面)

  • Factory Method 具体的创建者可以从一个接口创建,还是必须来自一个类? (类推迟实例化到子类)

  • 如果抽象工厂只能有一个创建者和一个产品,那么 Abstract FactoryFactory Method 之间唯一的区别是前者的创建者是一个接口而后者的创建者是一个类?

10 回答

  • 1

    希望这可以帮助 . 它描述了各种类型的工厂 . 我用Head First Design Patterns作为参考 . 我用yuml.me来图 .

    Static Factory

    是一个带有静态方法的类,用于生成各种子类型的Product .

    Static Factory

    Simple Factory

    是一个可以生成各种子类型的产品的类 . (它比静态工厂更好 . 当添加新类型时,基础Product类不需要仅更改Simple Factory Class)

    Simple Factoryt

    Factory Method

    包含一种生成与其类型相关的产品类型的方法 . (它比简单工厂更好,因为类型被推迟到子类 . )

    Factory Method

    Abstract Factory

    生成相关的类型系列 . 它与工厂方法明显不同,因为它有多种类型的方法 . (这很复杂,请参考下图以获得更好的实际例子) .

    Abstract Factory

    Example From The .NET Framework

    DbFactoriesProvider是一个简单工厂,因为它没有子类型 . DbFactoryProvider是一个抽象工厂,因为它可以创建各种相关的数据库对象,如连接和命令对象 .

    Abstract Factory From .NET Framework

  • 13

    这两种模式肯定是相关的!

    模式之间的差异通常是故意的 .

    Factory Methodintent 是"Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses."

    Abstract Factoryintent 是"Provide an interface for creating families of related or dependent objects without specifying their concrete classes."

    纯粹基于这些意图陈述(引自GoF),我会说 Factory Method 在某种意义上确实是"degenerate" Abstract Factory 与一个一族 .

    它们通常在实现上有所不同,因为 Factory MethodAbstract Factory 更简单 .

    然而,它们也与实施有关 . 正如GoF书中所述,

    AbstractFactory仅声明用于创建产品的接口 . 由ConcreteProduct子类实际创建它们 . 最常见的方法是为每个产品定义工厂方法 .

    这个c2 wiki也就这个话题进行了一些有趣的讨论 .

  • 0

    似乎OP的(优秀)问题清单被忽略了 . 目前的答案仅提供重新定义的定义 . 因此,我将简要地尝试解决原始问题 .

    如果抽象工厂只有一个创建者和一个产品,它仍然是抽象工厂模式吗? (创建家庭的界面)

    不可以 . 抽象工厂必须创建多个产品来制作"family of related products" . 规范的GoF示例创建 ScrollBar()Window() . 优点(和目的)是抽象工厂可以在其多个产品中实施共同主题 .

    可以从接口创建工厂方法具体创建者还是必须来自类? (类推迟实例化到子类)

    首先,我们必须注意,当GoF编写他们的书时,Java和C#都不存在 . GoF对术语接口的使用与特定语言引入的接口类型无关 . 因此,可以从任何API创建具体创建者 . 模式中的重点是API使用自己的工厂方法,因此只有一个方法的接口不能是工厂方法,它可以是一个抽象工厂 .

    如果抽象工厂只能有一个创建者和一个产品,那么抽象工厂和工厂方法之间的唯一区别是前者的创建者是一个接口而后者的创建者是一个类?

    根据上述答案,此问题不再有效;但是,如果你被认为是唯一的区别Abstract Factory和Factory Method之间的关系是创建的产品数量,考虑客户如何使用这些模式 . 抽象工厂通常被注入其客户端并通过组合/委托调用 . 必须继承工厂方法 . 所以这一切都回到了旧的构成与继承辩论 .

    但这些答案提出了第四个问题!

    因为,只有一个方法的接口不能是一个工厂方法,它可以是一个抽象工厂,我们称之为只有一个方法的创建接口?

    如果该方法是静态的,则通常称为 Static Factory . 如果该方法是非静态的,则通常称为 Simple Factory . 这些都不是GoF模式,但在实践中它们更常用!

  • 4

    在我看来,两种模式之间的细微差别在于 applicability ,正如已经说过的那样,在 Intent 中 .

    让我们回顾一下定义(都来自维基百科) .

    Abstract Factory

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

    Factory Method

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

    这两种模式都允许将用户对象与创建所需实例(运行时解耦)分离,这是常见的方面 . 这两种模式都允许根据任何特定需求创建工厂层次结构,这是另一个常见方面 .

    Abstract Factory允许在一个子类中创建几种不同类型的实例,并在其不同的子类中具体化创建行为;通常,Factory方法声明只创建一种类型的对象,可以根据子分类机制进行细化 . 这就是区别 .

    通过总结 . 假设Product定义了创建对象的超类,ProductA和ProductB是两个不同的子类 . 因此,Abstract Factory方法将有两个方法,createProductA()和createProductB(),它们将在其特定的子类中具体化(就创建步骤而言):工厂子类特定于两个定义的类的创建步骤正在创建的对象 .

    根据上面的示例,Factory方法将以不同的方式实现,在尽可能多的工厂(每个工厂一个方法)中抽象ProductA和ProductB的创建,并且在构建时将创建步骤的进一步专业化委托给层次结构 .

  • 75

    如果我创建了一个抽象的(通过接口或抽象基类引用)Factory类,它创建的对象只有一个方法来创建对象,那么它就是 Factory Method .

    如果抽象的Factory有多个方法来创建对象,那么它将是 Abstract Factory .

    假设我创建了一个Manager来处理MVC控制器的动作方法需求 . 如果它有一个方法,比如说创建将用于创建视图模型的引擎对象,那么它将是一个工厂方法模式 . 另一方面,如果它有两个方法:一个用于创建视图模型引擎,另一个用于创建动作模型引擎(或者您想要调用动作方法包含消费者的模型),那么它将是一个抽象工厂 .

    public ActionResult DoSomething(SpecificActionModel model)
    {
        var actionModelEngine = manager.GetActionModelEngine<SpecificActionModel>();
        actionModelEngine.Execute(SpecificActionModelEnum.Value);
    
        var viewModelEngine = manager.GetViewModelEngine<SpecificViewModel>();
        return View(viewModelEngine.GetViewModel(SpecificViewModelEnum.Value);
    }
    
  • 130

    尽管如此,自从StackOverflow的人们在其他帖子(最早到2009年)中对此问题提出质疑以来已经很多年了,但我仍然找不到我想要的答案 .


    所以我通过网络进行了几个小时的研究,回顾了这些例子,并得出了这个结论,抽象工厂与工厂方法的主要区别在于

    • The intention: coherence or "look-and-feel" :抽象工厂的目的是将具有相同样式的对象族(例如,相同的外观UI小部件,相同样式的汽车部件,来自相同OS的对象等)分组 . 来自抽象工厂的许多示例提到关键词"the same look-and-feel" .

    • Objects forming a bigger group object :Abstract Factory创建一个对象族,形成一个更大的组对象,而不是单个对象 .

    • Later add a new style :如果我们继续使用Factory Method并尝试向现有基础架构添加一组新样式,那将会非常痛苦 . 使用抽象工厂,我们只需要创建一个实现抽象工厂类的新混凝土工厂 .

    反例是

    • 用于轿车的跑车的汽车零件 . 这种不一致可能导致事故 .

    • 不同OS GUI小部件中的Windows样式按钮 . 它不会破坏任何东西,但会伤害某些人的用户体验,就像我一样 .

    • 后来,我们发现我们的软件需要在下一次操作系统升级中运行,这需要不同的兼容系统对象集,同时保持软件向后兼容 .

    因此,当最终对象组应具有相同的样式时 without an exception 一个对象并且你要隐藏这个"keeping the same style"细节,那么我们应该使用Abstract Factory .

  • 2

    据我所知,抽象工厂和工厂方法定义的含义是第一个在静态上下文中实现,并根据输入参数提供对象 .

    第二个使用已经创建的对象(系列)来实现工厂方法接口 . 然后,工厂方法创建与原始对象相关的特定实例,无论它是哪一个 .

    因此,这通常会导致将两个模式结合使用,在第一步中,您将创建一些描述相关对象族的通用对象 . 它由静态方法getInstance(“我的姓氏”)方法调用 . 这种getInstance方法的实现决定了将创建哪个系列对象 .

    然后我在新创建的族对象上调用createProduct()方法,并根据族对象返回新产品 .

    似乎这些模式与每个模式相互配合 .

    换句话说,抽象工厂专注于将创建“什么”,并且将创建工厂方法“如何” .

  • 0

    All you have to remember is that a abstract factory is a factory that can return a multiple factories . 所以如果你有一个AnimalSpeciesFactory它可以返回这样的工厂:

    Mamalfactory,BirdFactory,Fishfactory,ReptileFactory . 既然您拥有AnimalSpeciesFactory中的单个工厂,他们就会使用工厂模式来创建特定的对象 . 例如,假设您从这个AnimalFactory获得了一个ReptileFactory,那么您可以提供创建爬行动物对象,如:蛇,海龟,蜥蜴对象 .

  • 0

    工厂方法模式是一种创建设计模式,它处理创建对象而不显示正在创建的对象的确切类 . 这种设计模式基本上允许类将实例化推迟到子类 .

    抽象工厂模式为一组单独的工厂提供封装,而不暴露具体类 . 在此模型中,抽象工厂类的通用接口用于创建所需的具体对象,将对象的实现细节与其使用和组合分开 . 此设计模式广泛用于需要创建类似GUI组件的GUI应用程序中 .

    在google上搜索时,我发现了博客,它解释了两种设计模式 . 看看这些

    http://simpletechtalks.com/factory-design-pattern/

    http://simpletechtalks.com/abstract-factory-design-pattern/

  • 0
    /*
    //Factory methods:
    
    //1. Factory Method - Abstract Creator Class
    
    
    
    #include <iostream>
    #include <string.h>
    using namespace std;
    
    const std::string nineNintyCC = std::string("990CC");
    const std::string thousandTwoHundredCC = std::string("1200CC");
    const std::string ThousandFiveHundredCC = std::string("1500CC");
    const std::string fiveThousandCC = std::string("5000CC");
    
    // Product
    class Engine
    {
        public:
        virtual void packEngine() = 0;  
    };
    
    // Concrete products
    // concrete product class one
    class C990CCEngine: public Engine
    {
    
        public:
        void packEngine()
        {
           cout << "Pack 990CC engine" << endl;   
        }
    };
    
    // concrete class Two
    class C1200CCEngine: public Engine
    {   public:
        void packEngine()
        {
            cout << "pack 1200CC engine" << endl;
        }
    
    };
    
    // Concrete class Three
    class C1500CCEngine: public Engine
    {
        public:
        void packEngine()
        {
            cout << "Pack 1500CC engine" << endl;
        }
    
    };
    
    
    // Car Factory:
    class CarFactory{
        public:
    
        virtual Engine* createEngine(const std::string& type) = 0;
    };
    class Factory: public CarFactory
    {
        public:
         Engine *createEngine(const std::string& type)
         {
    
              if(0 == nineNintyCC.compare(type))
              {    
                 return new C990CCEngine;
              }
              else if(0 == thousandTwoHundredCC.compare(type))
              {
                 return new C1200CCEngine;
              }
              else if(0 == ThousandFiveHundredCC.compare(type))
              {
                 return new C1500CCEngine;
              } 
              else
               {
                     cout << "Invalid factory input" << endl;
                 return NULL;
               }
               return NULL;
         }
    };
    
    int main()
    {
    
        CarFactory* ptr = new Factory;
        Engine*pEngine =  ptr->createEngine(nineNintyCC);
        if(pEngine)
        {
            pEngine->packEngine();
            delete pEngine;
        }
        else
        {
            cout << "No engine exists of your type in our factory" << endl;
        }
        pEngine =  ptr->createEngine(ThousandFiveHundredCC);
        if(pEngine)
        {
            pEngine->packEngine();
            delete pEngine;
        }
        else
        {
            cout << "No engine exists of your type in our factory" << endl;
        }
        pEngine =  ptr->createEngine(thousandTwoHundredCC);
        if(pEngine)
        {
            pEngine->packEngine();
            delete pEngine;
        }
        else
        {
            cout << "No engine exists of your type in our factory" << endl;
        }
        pEngine = ptr-> createEngine(fiveThousandCC);
        if(pEngine)
        {
            pEngine->packEngine();
            delete pEngine;
        }
        else
        {
            cout << "No engine exists of your type in our factory" << endl;
        }
        return 0;
    }
    
    */
    /*
    //
    // interface product
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Engine
    {
     public:
     virtual void EngineType() = 0;
    
    };
    
    // concrte product
    class AltoEngine: public Engine
    {
      public:
      void EngineType()
      {
          cout << "Alto Engine" << endl;
      }
    };
    
    //Concrte product
    class SwiftEngine : public Engine
    {
        public:
        void EngineType()
        {
            cout << "Swift Engine" << endl;    
        }
    };
    
    class Body
    {
       public:
        virtual void bodyType() = 0;
    
    };
    
    class AltoBody: public Body
    {
      public:  
        virtual void bodyType()
        {
            cout << "Alto Car Body" << endl;
        }
    };
    
    class SwiftBody : public Body
    {
        public:
        void bodyType()
        {
            cout << "SwiftCar Body" << endl;
        }
    
    };
    
    
    class CarFactory
    {
       public:
       virtual Engine* createEngineProduct() = 0;
       virtual Body*   createBodyPoduct() = 0;
    };
    class AltoCarFactory: public CarFactory
    {
        public:
        Engine * createEngineProduct()
        {
            return new AltoEngine;
        }
        Body* createBodyPoduct()
        {
            return new AltoBody;
        }
    
    };
    
    class SwiftCarFactory: public CarFactory
    {
        public:
        Engine * createEngineProduct()
        {
            return new SwiftEngine;
        }
        Body* createBodyPoduct()
        {
            return new SwiftBody;
        }
    
    };
    
    int main()
    {
    
        CarFactory* pAltoFactory = new AltoCarFactory;
        Engine* pAltoEngine = pAltoFactory->createEngineProduct();
        pAltoEngine->EngineType();
        Body* pAltoBody = pAltoFactory->createBodyPoduct();
        pAltoBody->bodyType();
    
    
    
        CarFactory* pSwiftFactory = NULL;
        pSwiftFactory = new SwiftCarFactory;
        Engine* pSwiftEngine = pSwiftFactory->createEngineProduct();
        pSwiftEngine->EngineType();
        Body* pSwfitBody = pSwiftFactory->createBodyPoduct();
        pSwfitBody->bodyType();
        delete pAltoBody;
        delete pAltoFactory;
        delete pSwfitBody;
        delete pSwiftFactory;
        return 0;
    }
    */
    
    /*
    
    // One more Factory example;
    
    #include <iostream>
    #include <string>
    using namespace std;
    
    const std::string maruthi = std::string("Maruthi");
    const std::string fiat = std::string("Fiat");
    const std::string renault = std::string("Renault");
    // Interface
    class CarEngine
    {
     public:
        virtual void engineType() = 0;
    };
    
    // Concrete class
    class FiatEngine: public CarEngine
    {
      public:
      void engineType()
      {
          cout << "Fait Engine Engine" << endl;
      }
    
    };
    // ConcreteClass
    class RenaultEngine : public CarEngine
    {
        public:
        void engineType()
        {
            cout << "Renault Engine" << endl;
        }
    
    };
    // Concrete class
    class MaruthiEngine : public CarEngine
    {
        public:
        void engineType()
        {
            cout << "Maruthi Engine" << endl;
        }
    };
    
    
    // Factory
    class CarFactory
    {
        public:
        virtual CarEngine* createFactory(const std::string&) = 0;
    };
    
    // EngineFactory
    class CarEngineFactory : public CarFactory
    {
         public:
         CarEngine* createFactory(const std::string&  type)
         {
              if(0 == maruthi.compare(type))
              {
                  return new MaruthiEngine;
    
              }
              else if(0 == fiat.compare(type))
              {
                  return  new FiatEngine;
              }
              else if(0 == renault.compare(type))
              {
                  return new RenaultEngine;
              }
              else
              {
                  cout << "Invalid Engine type" << endl;
                  return NULL;
              }
         }
    
      };
    
    int main()
    {
        CarFactory* pCarFactory = new CarEngineFactory;
        CarEngine* pMaruthiCarEngine = pCarFactory->createFactory(maruthi);
        pMaruthiCarEngine->engineType();
    
        CarEngine* pFiatCarEngine = pCarFactory->createFactory(fiat);
        pFiatCarEngine->engineType();
    
    
        CarEngine* pRenaultCarEngine = pCarFactory->createFactory(renault);
        pRenaultCarEngine->engineType();
    
        return 0;
    }
    
    
    */
    
    
    /*
    
    // One more Factory example;
    
    #include <iostream>
    #include <string>
    using namespace std;
    
    const std::string maruthi = std::string("Maruthi");
    const std::string fiat = std::string("Fiat");
    const std::string renault = std::string("Renault");
    
    
    // Interface
    class CarEngine
    {
     public:
        virtual void engineType() = 0;
    };
    
    // Concrete class
    class FiatEngine: public CarEngine
    {
      public:
      void engineType()
      {
          cout << "Fait Car Engine" << endl;
      }
    
    };
    
    // ConcreteClass
    class RenaultEngine : public CarEngine
    {
        public:
        void engineType()
        {
            cout << "Renault Car Engine" << endl;
        }
    
    };
    
    // Concrete class
    class MaruthiEngine : public CarEngine
    {
        public:
        void engineType()
        {
            cout << "Maruthi Car Engine" << endl;
        }
    };
    
    // Interface
    class CarBody
    {
     public:
        virtual void bodyType() = 0;
    };
    
    // Concrete class
    class FiatBody: public CarBody
    {
      public:
      void bodyType()
      {
          cout << "Fait car Body" << endl;
      }
    
    };
    
    // ConcreteClass
    class RenaultBody : public CarBody
    {
        public:
        void bodyType()
        {
            cout << "Renault Body" << endl;
        }
    
    };
    
    // Concrete class
    class MaruthiBody : public CarBody
    {
        public:
        void bodyType()
        {
            cout << "Maruthi body" << endl;
        }
    };
    
    
    // Factory
    class CarFactory
    {
        public:
        virtual CarEngine* createCarEngineProduct() = 0;
        virtual CarBody* createCarBodyProduct() = 0;
    };
    
    // FiatFactory
    class FaitCarFactory : public CarFactory
    {
         public:
         CarEngine* createCarEngineProduct()
         {
            return new FiatEngine; 
         }
         CarBody* createCarBodyProduct()
         {
             return new FiatBody;
         }
    };
    
    // Maruthi Factory
    class MaruthiCarFactory : public CarFactory
    {
         public:
         CarEngine* createCarEngineProduct()
         {
             return new MaruthiEngine;
         }
         CarBody* createCarBodyProduct()
         {
             return new MaruthiBody;
         }
    
    };
    
    // Renault Factory
    class RenaultCarFactory : public CarFactory
    {
         public:
        CarEngine* createCarEngineProduct()
        {
            return new RenaultEngine;
        }
    
        CarBody* createCarBodyProduct()
        {
            return new RenaultBody;
        }
    
    };
    
    
    int main()
    {
    
       // Fiat Factory
       CarFactory* pFiatCarFactory = new FaitCarFactory;
       CarEngine* pFiatEngine = pFiatCarFactory->createCarEngineProduct();
       CarBody*  pFiatBody = pFiatCarFactory->createCarBodyProduct();
       pFiatEngine->engineType();
       pFiatBody->bodyType();
    
       // Renault Car Factory
        return 0;
    }
    
    */
    

相关问题