zoukankan      html  css  js  c++  java
  • 设计模式之实现几种工厂模式

    1.工厂方法模式:

    /*************************************

       CPizza.h

    *************************************/

    #pragma once
    #include <iostream>
    using namespace std;

    class CPizza
    {
    public:
     virtual string getDescription() = 0;
    };

    class CNYCheesePizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a new york cheese pizza");
     }
    };

    class CNYTomatoPizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a new york tomato pizza");
     }
    };

    class CNYMixPizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a new york mix pizza");
     }
    };

    class CChicagoCheesePizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a Chicago cheese pizza");
     }
    };

    class CChicagoTomatoPizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a Chicago tomato pizza");
     }
    };

    class CChicagoMixPizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a Chicago mix pizza");
     }
    };

    /**********************************************

    CPizzaStore.h

    *********************************************/

    #include <iostream>
    #include "CPizza.h"
    using namespace std;


    /*
    工厂方法是一种is-a的关系,这个是比萨店的虚基类。
    所有实比萨店必须要从这里派生出去,并重载

    也就是工厂方法与简单工厂的区别,工厂方法把工厂的实现延迟到子类去决定
    */

    class CPizzaStore
    {
    public:
     CPizza* orderPizza(const string& _pizzaName){

      //简单工厂方法,来做一个比萨
      CPizza* pizza = createPizza(_pizzaName);

      //对比萨做一些其它处理
      bake(pizza);
      cut(pizza);
      box(pizza);

      return pizza;
     }

     void bake(CPizza* pz){};

     void cut(CPizza* pz){};

     void box(CPizza* pz){};

     ////////////////////////////////////////////////////////////////////////
     //这个函数是工厂方法的根本。。。。。。。。。。。。。。。。。。。
     //子类必须将其重载
     virtual CPizza* createPizza(const string& _pizzaName) = 0;
    };

    //开一家纽约风味的比萨店,注意在这里要实现createPizza()工厂方法
    class CNYPizzaStore : public CPizzaStore
    {
    public:
     CPizza* createPizza(const string& _pizzaName){
      //查找pizza种类,做类型匹配
      map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
      if(ifind == g_pizzatype.end())
       return NULL;

      CPizza* pizza = NULL;

      switch(ifind->second)
      {
      case PT_CHEESE:
       pizza = new CNYCheesePizza();
       break;
      case PT_TOMATO:
       pizza = new CNYTomatoPizza();
       break;
      case PT_MIX:
       pizza = new CNYMixPizza();
       break;
      }

      return pizza;
     }
    };

    //开一家纽约风味的比萨店,注意在这里要实现真正的pizza类
    class CChicagoPizzaStore : public CPizzaStore
    {
    public:
     CPizza* createPizza(const string& _pizzaName){
      //查找pizza种类,做类型匹配
      map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
      if(ifind == g_pizzatype.end())
       return NULL;

      CPizza* pizza = NULL;

      switch(ifind->second)
      {
      case PT_CHEESE:
       pizza = new CChicagoCheesePizza();
       break;
      case PT_TOMATO:
       pizza = new CChicagoTomatoPizza();
       break;
      case PT_MIX:
       pizza = new CChicagoMixPizza();
       break;
      }

      return pizza;
     }
    };

    /*********************************************************

    PizzaType.h

    *********************************************************/

    #pragma once;
    #include <map>
    #include <string>
    using namespace std;

    enum pizzaType{
     PT_CHEESE = 1,
     PT_TOMATO,
     PT_MIX,
    };

    map<string, pizzaType> g_pizzatype;

    void buildMapping(map<string, pizzaType>& g_pizzatype)
    {
     g_pizzatype.insert(make_pair("cheese", PT_CHEESE));
     g_pizzatype.insert(make_pair("tomato", PT_TOMATO));
     g_pizzatype.insert(make_pair("mix", PT_MIX));
    }

    /**********************************************************

    main.h

    ***********************************************************/

    /*
    设计模式:  工厂方法模式: is a关系

    工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪些一个。工厂方法让类把实例化推迟到子类。
    所有的工厂模式都用来封闭对象的创建。工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封闭的目的。


    简单工厂与工厂方法之间的区别:
    1. 简单工厂是一种has-a的关系,所有的产口是由店铺中的一个工厂成员所创建的。而工厂方法是一种is-a的关系,它把创建产品的事情留给了工厂方法的子类去决定如何创建。
    2. 简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。
    3. 简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

    抽象工厂与工厂方法的区别:
    1. 工厂方法用的是继承, 抽象工厂用的是组合。
    这就意味着用工厂方法创建对象需要扩展一个类,并覆盖它的工作方法。工厂方法通过子类来创建对象。用这种做法,客户只需只知道他们所使用的抽象类型就可以了,而由子类来负责决定具体类型。换句话说,工厂方法只负责将客户从具体类型中解耦。
    抽象工厂提供一个用来创建一个“产品家族”的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码事。所以,和工厂方法一样,抽象工厂也可以将客户从具体类型中解耦。要创建产品家族中的某个产品,我们可以通过调用抽象工厂的对应生产此产品的方法。这些方法必须要抽象工厂的实体子类中重载实现。
    2. 扩展性和修改性
    对于抽象工厂,如果想在“产品家族”中加入新(修改)产品就必须新增(改变)其抽象的接口,改变接口就是意味着必须深入改变每个子类的接口!
    而工厂方法不存在这个问题,因为工厂方法只是用来创建一个产品。:(


    by 何戬, hejian@cad.zju.edu.cn
    */


    #include <iostream>
    #include "pizzaType.h"
    #include "CPizzaStore.h"
    using namespace std;

    int main()

     buildMapping(g_pizzatype);

     /*//类型匹配
     map<string, pizzaType>::iterator ifind = g_pizzatype.find("cheese");
     if(ifind == g_pizzatype.end())
     return 0;
     cout<<ifind->first<<ifind->second<<endl;
     */

     CPizzaStore* nypizzaStore = new CNYPizzaStore();
     CPizza* p1 = nypizzaStore->orderPizza("cheese");
     CPizza* p2 = nypizzaStore->orderPizza("mix");
     cout<<p1->getDescription()<<endl;
     cout<<p2->getDescription()<<endl;

     CPizzaStore* chipizzaStore = new CChicagoPizzaStore();
     CPizza* p3 = chipizzaStore->orderPizza("cheese");
     CPizza* p4 = chipizzaStore->orderPizza("mix");
     cout<<p3->getDescription()<<endl;
     cout<<p4->getDescription()<<endl;


     delete p4;
     delete p3;
     delete p2;
     delete p1;
     delete nypizzaStore;

     return 0;
    }

    2.简单工厂:

    /***************************************************************

    CPizza.h

    ***************************************************************/

    #pragma once
    #include <iostream>
    using namespace std;

    class CPizza
    {
    public:
     virtual string getDescription() = 0;
    };

    class CCheesePizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a cheese pizza");
     }
    };

    class CTomatoPizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a tomato pizza");
     }
    };

    class CMixPizza : public CPizza
    {
    public:
     string getDescription(){
      return string("a mix pizza");
     }
    };

    /********************************************************

    CPizzaStore.h

    ********************************************************/

    #include <iostream>
    #include "simpleFactory.h"
    using namespace std;


    /*
    简单工厂是一种has-a的关系,所有的产口是由店铺中的一个工厂成员所创建的。
    */
    class CPizzaStore
    {
    private:
     //用于产生比萨的工厂
     CSimpleFactory* m_PizzaFactory;

    public:
     //用策略模式来更改工厂
     void setNewFactory(CSimpleFactory* _PizzaFactory){
      if(!_PizzaFactory)
       return;
      m_PizzaFactory = _PizzaFactory;
     }

     CPizzaStore(CSimpleFactory* _PizzaFactory){
      m_PizzaFactory = _PizzaFactory;
     }

     CPizza* orderPizza(const string& _pizzaName){
      if(!m_PizzaFactory)
       return NULL;

      //简单工厂方法,来做一个比萨
      CPizza* pizza = m_PizzaFactory->makePizza(_pizzaName);

      //对比萨做一些其它处理
      bake(pizza);
      cut(pizza);
      box(pizza);

      return pizza;
     }

     void bake(CPizza* pz){};

     void cut(CPizza* pz){};

     void box(CPizza* pz){};
    };

    /******************************************************

    pizzaType.h

    ******************************************************/

    #pragma once;
    #include <map>
    #include <string>
    using namespace std;

    enum pizzaType{
     PT_CHEESE = 1,
     PT_TOMATO,
     PT_MIX,
    };

    map<string, pizzaType> g_pizzatype;

    void buildMapping(map<string, pizzaType>& g_pizzatype)
    {
     g_pizzatype.insert(make_pair("cheese", PT_CHEESE));
     g_pizzatype.insert(make_pair("tomato", PT_TOMATO));
     g_pizzatype.insert(make_pair("mix", PT_MIX));
    }

    /********************************************************

    simpleFactory.h

    ********************************************************/

    /*
     一个简单工厂的类
    */

    #include <iostream>
    #include "pizzaType.h"
    #include "CPizza.h"
    using namespace std;

    class CSimpleFactory
    {
    public:

     CPizza* makePizza(const string& pizzaname){

      //查找pizza种类,做类型匹配
      map<string, pizzaType>::iterator ifind = g_pizzatype.find(pizzaname);
      if(ifind == g_pizzatype.end())
       return NULL;

      CPizza* pizza = NULL;
      
      switch(ifind->second)
      {
      case PT_CHEESE:
       pizza = new CCheesePizza();
       break;
      case PT_TOMATO:
       pizza = new CTomatoPizza();
       break;
      case PT_MIX:
       pizza = new CMixPizza();
       break;
      }

      return pizza;
     }
    };

    /*************************************************

    testSimpleFactory.cpp

    *************************************************/

    /*
        设计模式:  简单工厂, has a 关系

     简单工厂其实不是一个设计模式,反而比较是一种编程习惯。但经常被使用。
     虽然我们可以定义一个静态的工厂方法(称为静态工厂),这样可以避免实例化一个工厂类。但是,这样做的话就不能通过继承来改变创建方法的行为。


     简单工厂与工厂方法之间的区别:
     1. 简单工厂是一种has-a的关系,所有的产口是由店铺中的一个工厂成员所创建的。而工厂方法是一种is-a的关系,它把创建产品的事情留给了工厂方法的子类去决定如何创建。
     2. 简单工厂把全部的事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。
     3. 简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

     by 何戬, hejian@cad.zju.edu.cn
    */
    #include <iostream>
    #include "pizzaType.h"
    #include "CPizzaStore.h"
    using namespace std;


    int main()
    {
     buildMapping(g_pizzatype);
     
     /*//类型匹配
     map<string, pizzaType>::iterator ifind = g_pizzatype.find("cheese");
     if(ifind == g_pizzatype.end())
      return 0;
     cout<<ifind->first<<ifind->second<<endl;
     */

     CSimpleFactory* sf = new CSimpleFactory();

     CPizzaStore* pizzaStore = new CPizzaStore(sf);

     CPizza* aCheesPizza = pizzaStore->orderPizza("tomato");
     cout<<aCheesPizza->getDescription()<<endl;;

     delete aCheesPizza;
     delete pizzaStore;
     delete sf;

     return 0;
    }

    3.抽象工厂模式

    /*
        抽象工厂的方法经常以工厂方法的方式实现。
     抽象工厂的任务是定义一个负责创建"一组"产品的接口。
     这个接口内的每个方法都负责创建一个具体产品。
     同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以在抽象工厂中利用工厂方法是相当自然的做法。

     by 何戬, hejian@cad.zju.edu.cn
    */

    /*******************************************************

    AbstractFactory.h

    *******************************************************/


    #pragma once
    #include <iostream>
    #include "pizzaType.h"
    #include "CPizza.h"
    #include "CIngredient.h"
    using namespace std;


    //////////////////////////////////////////////////
    //抽象工厂模式的虚基类
    //虚基类定义了创建对象家族的接口
    //一般地,每一个对象用一个接口来创建
    //暂定这个抽象工厂是用来
    class CAbstractIngredientFactory
    {
     /*
     tomato和sugar是可以看成是同一家庭的产品
     */
    public:
     //定义创建tomato对象的基类成员
     virtual CTomato* getTomato() = 0;
     //定义创建Sugar对象的基类成员
     virtual CSugar*  getSugar() = 0;
    };


    ///////////////////////////////////////////////
    //定义一个纽约的原料工厂
    class CNYIngredientFactory : public CAbstractIngredientFactory
    {
    public:
     virtual CTomato* getTomato(){
      return new CSweetTomato();
     }

     virtual CSugar* getSugar(){
      return new CWhiteSugar();
     }
    };

    ///////////////////////////////////////////////
    //定义一个纽约的原料工厂
    class CChicagoIngredientFactory : public CAbstractIngredientFactory
    {
    public:
     virtual CTomato* getTomato(){
      return new CCommonTomato();
     }

     virtual CSugar* getSugar(){
      return new CRedSugar();
     }
    };

    /**********************************************************

    CIngredient.h

    **********************************************************/

    #pragma once
    #include <iostream>
    using namespace std;

    //比萨成份类

    //tomato的基类
    class CTomato
    {
    public:
     virtual string getDescription() = 0;
    };

    //非常甜的Tomato
    class CSweetTomato : public CTomato
    {
    public:
     virtual string getDescription(){
      return "ingredient: sweet tomato";
     }
    };

    //普通Tomato
    class CCommonTomato : public CTomato
    {
    public:
     virtual string getDescription(){
      return "ingredient: common tomato";
     }
    };

    //Sugar的基类
    class CSugar
    {
    public:
     virtual string getDescription() = 0;
    };

    //白糖
    class CWhiteSugar : public CSugar
    {
    public:
     string getDescription(){
      return "ingredient: White Sugar";
     }
    };

    //红糖
    class CRedSugar : public CSugar
    {
    public:
     string getDescription(){
      return "ingredient: Red Sugar";
     }
    };

     /***********************************************************

    CPizza.h

    ***********************************************************/

    #pragma once
    #include <iostream>
    #include "CIngredient.h"
    #include "AbstractFactory.h"
    using namespace std;

    /////////////////////////////////////
    //用抽象工厂来产生原料的比萨基类
    class CPizza
    {
    protected:
     CTomato* m_ingedientTomato;
     CSugar*  m_ingredientSugar;

    public:
     CPizza():m_ingedientTomato(NULL), m_ingredientSugar(NULL){};
     virtual string getDescription() = 0;
    };

    //现在制作哪个口味的比萨就是由原料工厂参数来定了。
    class CCheesePizza : public CPizza
    {
    public:
     CCheesePizza(CAbstractIngredientFactory* _ingredientFactory){
      m_ingedientTomato   = _ingredientFactory->getTomato();
      m_ingredientSugar   = _ingredientFactory->getSugar();
     }
     string getDescription(){
      if(!m_ingedientTomato || !m_ingredientSugar)
       return "";
      string res("a new york cheese pizza");
      res += "\nTomato :";
      res += m_ingedientTomato->getDescription();
      res += "\nSugar :";
      res += m_ingredientSugar->getDescription();
      return res;
     }
    };

    class CTomatoPizza : public CPizza
    {
    public:
     CTomatoPizza(CAbstractIngredientFactory* _ingredientFactory){
      m_ingedientTomato   = _ingredientFactory->getTomato();
      m_ingredientSugar   = _ingredientFactory->getSugar();
     }

     string getDescription(){
      if(!m_ingedientTomato || !m_ingredientSugar)
       return "";
      string res("a new york tomato pizza");
      res += "\nTomato :";
      res += m_ingedientTomato->getDescription();
      res += "\nSugar :";
      res += m_ingredientSugar->getDescription();
      return res;
     }
    };

    class CMixPizza : public CPizza
    {
    public:
     CMixPizza(CAbstractIngredientFactory* _ingredientFactory){
      m_ingedientTomato   = _ingredientFactory->getTomato();
      m_ingredientSugar   = _ingredientFactory->getSugar();
     }

     string getDescription(){
      if(!m_ingedientTomato || !m_ingredientSugar)
       return "";
      string res("a new york mix pizza");
      res += "\nTomato :";
      res += m_ingedientTomato->getDescription();
      res += "\nSugar :";
      res += m_ingredientSugar->getDescription();
      return res;
     }
    };

    /***********************************************************

    CPizzaStore.h

    **********************************************************/

    #pragma once
    #include <iostream>
    #include "CPizza.h"
    #include "AbstractFactory.h"
    using namespace std;


    /*
    抽象工厂
    */

    class CPizzaStore
    {
    protected:
     //抽象工厂的成员变量,用来获取想要的调料
     CAbstractIngredientFactory* m_ingredientFactory;

    public:
     CPizzaStore() : m_ingredientFactory(NULL){}

     CPizza* orderPizza(const string& _pizzaName){

      //简单工厂方法,来做一个比萨
      CPizza* pizza = createPizza(_pizzaName);

      //对比萨做一些其它处理
      bake(pizza);
      cut(pizza);
      box(pizza);

      return pizza;
     }

     void bake(CPizza* pz){};

     void cut(CPizza* pz){};

     void box(CPizza* pz){};

     ////////////////////////////////////////////////////////////////////////
     //这个函数是工厂方法的根本。。。。。。。。。。。。。。。。。。。
     //子类必须将其重载
     virtual CPizza* createPizza(const string& _pizzaName) = 0;
    };

    //开一家纽约风味的比萨店,注意在这里要实现createPizza()工厂方法
    class CNYPizzaStore : public CPizzaStore
    {
    public:
     CNYPizzaStore(){
      m_ingredientFactory = new CNYIngredientFactory();
     }

     
     CPizza* createPizza(const string& _pizzaName){
      //查找pizza种类,做类型匹配
      map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
      if(ifind == g_pizzatype.end())
       return NULL;

      CPizza* pizza = NULL;

      switch(ifind->second)
      {
      case PT_CHEESE:
       pizza = new CCheesePizza(m_ingredientFactory);
       break;
      case PT_TOMATO:
       pizza = new CTomatoPizza(m_ingredientFactory);
       break;
      case PT_MIX:
       pizza = new CMixPizza(m_ingredientFactory);
       break;
      }
      return pizza;
     }
    };

    //开一家纽约风味的比萨店,注意在这里要实现真正的pizza类
    class CChicagoPizzaStore : public CPizzaStore
    {
    public:
     CChicagoPizzaStore(){
      m_ingredientFactory = new CChicagoIngredientFactory();
     }

     CPizza* createPizza(const string& _pizzaName){
      //查找pizza种类,做类型匹配
      map<string, pizzaType>::iterator ifind = g_pizzatype.find(_pizzaName);
      if(ifind == g_pizzatype.end())
       return NULL;

      CPizza* pizza = NULL;

      switch(ifind->second)
      {
      case PT_CHEESE:
       pizza = new CCheesePizza(m_ingredientFactory);
       break;
      case PT_TOMATO:
       pizza = new CTomatoPizza(m_ingredientFactory);
       break;
      case PT_MIX:
       pizza = new CMixPizza(m_ingredientFactory);
       break;
      }

      return pizza;
     }
    };

    /************************************************************

    pizzaType.h

    ***********************************************************/

    #pragma once;
    #include <map>
    #include <string>
    using namespace std;

    enum pizzaType{
     PT_CHEESE = 1,
     PT_TOMATO,
     PT_MIX,
    };

    map<string, pizzaType> g_pizzatype;

    void buildMapping(map<string, pizzaType>& g_pizzatype)
    {
     g_pizzatype.insert(make_pair("cheese", PT_CHEESE));
     g_pizzatype.insert(make_pair("tomato", PT_TOMATO));
     g_pizzatype.insert(make_pair("mix", PT_MIX));
    }

    /******************************************

    testAbstractFactory.cpp

    *******************************************/

    /*
    设计模式:  抽象工厂模式: has a关系

    提供一个接口,用于创建相关或依赖对象的"家族",而不需要明确指定具体类。
    抽象工厂的方法经常以工厂方法的方式实现。抽象工厂的任务是定义一个负责创建一组产品的接口。
    这个接口内的每个方法都负责创建一个具体产品。同时我们利用实现抽象工厂的子类来提供这些具体的做法。所以在抽象工厂中利用工厂方法是相当自然的做法。


    抽象工厂与工厂方法的区别:
    1. 工厂方法用的是继承, 抽象工厂用的是组合。
    这就意味着用工厂方法创建对象需要扩展一个类,并覆盖它的工作方法。工厂方法通过子类来创建对象。用这种做法,客户只需只知道他们所使用的抽象类型就可以了,而由子类来负责决定具体类型。换句话说,工厂方法只负责将客户从具体类型中解耦。
    抽象工厂提供一个用来创建一个“产品家族”的抽象类型,这个类型的子类定义了产品被产生的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码事。所以,和工厂方法一样,抽象工厂也可以将客户从具体类型中解耦。要创建产品家族中的某个产品,我们可以通过调用抽象工厂的对应生产此产品的方法。这些方法必须要抽象工厂的实体子类中重载实现。
    2. 扩展性和修改性
    对于抽象工厂,如果想在“产品家族”中加入新(修改)产品就必须新增(改变)其抽象的接口,改变接口就是意味着必须深入改变每个子类的接口!
    而工厂方法不存在这个问题,因为工厂方法只是用来创建一个产品。:(


    by 何戬, hejian@cad.zju.edu.cn

    */

    #include <iostream>
    #include "pizzaType.h"
    #include "CPizzaStore.h"
    using namespace std;

    int main()

     buildMapping(g_pizzatype);

     CPizzaStore* nyps = new CNYPizzaStore();
     CPizza* p1 = nyps->orderPizza("tomato");
     cout<<p1->getDescription()<<endl;
     CPizza* p2 = nyps->orderPizza("mix");
     cout<<p2->getDescription()<<endl;


     CPizzaStore* cps = new CChicagoPizzaStore();
     CPizza* p3 = cps->orderPizza("cheese");
     cout<<p3->getDescription()<<endl;
     CPizza* p4 = cps->orderPizza("tomato");
     cout<<p4->getDescription()<<endl;

     delete p4;
     delete p3;
     delete cps;
     delete p2;
     delete p1;
     delete nyps;
    }

  • 相关阅读:
    Backbone中的model和collection在做save或者create操作时, 如何选择用POST还是PUT方法 ?
    Spring boot: Request method 'DELETE' not supported, Request method 'PUT' not supported, Request method 'POST' not supported
    Backbone.js 中的Model被Destroy后,不能触发success的一个原因
    eclipse里打开SWT项目找不到source/design的图形UI设计界面
    RHEL5.6配置本地yum源
    Linux环境下Apache反向代理金蝶中间件Apusic集群
    Linux环境下源码安装Apache2.2.25
    WIN7中Beyond Compare报错误“应用程序发生错误” 无法启动
    使用Navicat迁移MySQL数据至Oracle时大小写原因报“表或视图不存在”问题处理
    -Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match问题处理
  • 原文地址:https://www.cnblogs.com/skyofbitbit/p/2756428.html
Copyright © 2011-2022 走看看