• c++设计模式:抽象工厂模式(Abstract Factory Pattern)


    定义:

    抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

    场景:

    我们的披萨商店正在加速的扩建,已经接了好多城市的加盟邀请。可是各地口味不同,如果每个地市都定义不同的披萨类型,那么后期的维护将是十分头痛的,根据分析,我们披萨的种类是固定的,变动的其实就是披萨中添加的原料类型和原料的分量,因为不同的地方所生产的原料也是不同的。所以根据总部意见,打算在各地建立一个原料工厂,制作的披萨还是那些披萨,只是各地通过自己的工厂生产披萨的原料,加入到自己的披萨当中,这样,虽然生产的流程不变,但是最终的披萨口味确实符合了当地人民的需求。我们的披萨商店现在可以放心的到处开分店啦。

    类图:

    c++代码如下:

    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;

    class PizzaType
    {
    public:
    enum EPizzaType {cheese,veggie,clam,pepperoni};
    };

    class PizzaIngredientFactory
    {
    public:
    virtual string createDough() = 0;
    virtual string createSauce() = 0;
    virtual string createCheese() = 0;
    virtual void createVeggies(vector<string>& vVeggies) = 0;
    virtual string createPepperoni() = 0;
    virtual string createClam() = 0;
    };

    class NYPizzaIngredientFactory : public PizzaIngredientFactory
    {
    public:
    string createDough();
    string createSauce();
    string createCheese();
    void createVeggies(vector<string>& vVeggies);
    string createPepperoni();
    string createClam();
    };

    class ChicagoPizzaIngredientFactory : public PizzaIngredientFactory
    {
    public:
    string createDough();
    string createSauce();
    string createCheese();
    void createVeggies(vector<string>& vVeggies);
    string createPepperoni();
    string createClam();
    };

    class Pizza
    {
    public:
    Pizza(PizzaIngredientFactory* pIngredientFactory);
    virtual ~Pizza();
    virtual void prepare() = 0;
    virtual void bake();
    virtual void cut();
    virtual void box();
    string getName();
    void setName(string name);
    vector<string> m_vVeggies;
    protected:
    PizzaIngredientFactory* m_pIngredientFactory;
    string m_sName;
    string m_sDough;
    string m_sSauce;
    string m_sCheese;
    string m_sPepperoni;
    string m_sClam;
    };

    class CheesePizza : public Pizza
    {
    public:
    CheesePizza(PizzaIngredientFactory* pIngredientFactory):Pizza(pIngredientFactory) {};
    void prepare();
    };

    class VeggiePizza : public Pizza
    {
    public:
    VeggiePizza(PizzaIngredientFactory* pIngredientFactory):Pizza(pIngredientFactory) {};
    void prepare();
    };

    class ClamPizza : public Pizza
    {
    public:
    ClamPizza(PizzaIngredientFactory* pIngredientFactory):Pizza(pIngredientFactory) {};
    void prepare();
    };

    class PepperoniPizza : public Pizza
    {
    public:
    PepperoniPizza(PizzaIngredientFactory* pIngredientFactory):Pizza(pIngredientFactory) {};
    void prepare();
    };

    class PizzaStore
    {
    public:
    Pizza* orderPizza(PizzaType::EPizzaType type);
    private:
    virtual Pizza* createPizza(PizzaType::EPizzaType type) = 0;
    };

    class NYPizzaStore : public PizzaStore
    {
    private:
    Pizza* createPizza(PizzaType::EPizzaType type);
    };

    class ChicagoPizzaStore : public PizzaStore
    {
    private:
    Pizza* createPizza(PizzaType::EPizzaType type);
    };

    string NYPizzaIngredientFactory::createDough()
    {
    return "Thin Crust Dough";
    }

    string NYPizzaIngredientFactory::createSauce()
    {
    return "Marinara Sauce";
    }

    string NYPizzaIngredientFactory::createCheese()
    {
    return "Reggiano Cheese";
    }

    void NYPizzaIngredientFactory::createVeggies(vector<string>& vVeggies)
    {
    vVeggies.push_back("Garlic");
    vVeggies.push_back("Onion");
    vVeggies.push_back("Mushrooms");
    vVeggies.push_back("Red Pepper");
    }

    string NYPizzaIngredientFactory::createPepperoni()
    {
    return "Sliced Pepperoni";
    }

    string NYPizzaIngredientFactory::createClam()
    {
    return "Fresh Clams from Long Island Sound";
    }

    string ChicagoPizzaIngredientFactory::createDough()
    {
    return "ThickCrust style extra thick crust dough";
    }

    string ChicagoPizzaIngredientFactory::createSauce()
    {
    return "Tomato sauce with plum tomatoes";
    }

    string ChicagoPizzaIngredientFactory::createCheese()
    {
    return "Shredded Mozzarella";
    }

    void ChicagoPizzaIngredientFactory::createVeggies(vector<string>& vVeggies)
    {
    vVeggies.push_back("Black Olives");
    vVeggies.push_back("Spinach");
    vVeggies.push_back("Eggplant");
    }

    string ChicagoPizzaIngredientFactory::createPepperoni()
    {
    return "Sliced Pepperoni";
    }

    string ChicagoPizzaIngredientFactory::createClam()
    {
    return "Frozen Clams from Chesapeake Bay";
    }

    Pizza::Pizza(PizzaIngredientFactory* pIngredientFactory)
    {
    m_pIngredientFactory = pIngredientFactory;
    }

    Pizza::~Pizza()
    {
    delete m_pIngredientFactory;
    }

    void Pizza::bake()
    {
    printf("Bake for 25 minutes at 350\n");
    }

    void Pizza::cut()
    {
    printf("Cutting the pizza into diagonal slices\n");
    }

    void Pizza::box()
    {
    printf("Place pizza in official PizzaStore box\n");
    }

    string Pizza::getName()
    {
    return m_sName;
    }

    void Pizza::setName(string name)
    {
    m_sName = name;
    }

    void CheesePizza::prepare()
    {
    printf("Preparing %s\n",m_sName.c_str());
    m_sDough = m_pIngredientFactory->createDough();
    m_sSauce = m_pIngredientFactory->createSauce();
    m_sCheese = m_pIngredientFactory->createCheese();
    }

    void VeggiePizza::prepare()
    {
    printf("Preparing %s\n",m_sName.c_str());
    m_sDough = m_pIngredientFactory->createDough();
    m_sSauce = m_pIngredientFactory->createSauce();
    m_sCheese = m_pIngredientFactory->createCheese();
    m_pIngredientFactory->createVeggies(m_vVeggies);
    }

    void ClamPizza::prepare()
    {
    printf("Preparing %s\n",m_sName.c_str());
    m_sDough = m_pIngredientFactory->createDough();
    m_sSauce = m_pIngredientFactory->createSauce();
    m_sCheese = m_pIngredientFactory->createCheese();
    m_sClam = m_pIngredientFactory->createClam();
    }

    void PepperoniPizza::prepare()
    {
    printf("Preparing %s\n",m_sName.c_str());
    m_sDough = m_pIngredientFactory->createDough();
    m_sSauce = m_pIngredientFactory->createSauce();
    m_sCheese = m_pIngredientFactory->createCheese();
    m_pIngredientFactory->createVeggies(m_vVeggies);
    m_sPepperoni = m_pIngredientFactory->createPepperoni();
    }

    Pizza* PizzaStore::orderPizza(PizzaType::EPizzaType type)
    {
    Pizza* pPizza = createPizza(type);
    printf("--- Making a %s ---\n",pPizza->getName().c_str());
    pPizza->prepare();
    pPizza->bake();
    pPizza->cut();
    pPizza->box();
    return pPizza;
    }

    Pizza* NYPizzaStore::createPizza(PizzaType::EPizzaType type)
    {
    Pizza* pPizza = NULL;
    PizzaIngredientFactory* pIngredientFactory = new NYPizzaIngredientFactory();

    if (PizzaType::cheese == type)
    {
    pPizza = new CheesePizza(pIngredientFactory);
    pPizza->setName("New York Style Cheese Pizza");
    }
    else if (PizzaType::veggie == type)
    {
    pPizza = new VeggiePizza(pIngredientFactory);
    pPizza->setName("New York Style Veggie Pizza");
    }
    else if (PizzaType::clam == type)
    {
    pPizza = new ClamPizza(pIngredientFactory);
    pPizza->setName("New York Style Clam Pizza");
    }
    else if (PizzaType::pepperoni == type)
    {
    pPizza = new PepperoniPizza(pIngredientFactory);
    pPizza->setName("New York Style Pepperoni Pizza");
    }
    return pPizza;
    }

    Pizza* ChicagoPizzaStore::createPizza(PizzaType::EPizzaType type)
    {
    Pizza* pPizza = NULL;
    PizzaIngredientFactory* pIngredientFactory = new ChicagoPizzaIngredientFactory();

    if (PizzaType::cheese == type)
    {
    pPizza = new CheesePizza(pIngredientFactory);
    pPizza->setName("Chicago Style Cheese Pizza");
    }
    else if (PizzaType::veggie == type)
    {
    pPizza = new VeggiePizza(pIngredientFactory);
    pPizza->setName("Chicago Style Veggie Pizza");
    }
    else if (PizzaType::clam == type)
    {
    pPizza = new ClamPizza(pIngredientFactory);
    pPizza->setName("Chicago Style Clam Pizza");
    }
    else if (PizzaType::pepperoni == type)
    {
    pPizza = new PepperoniPizza(pIngredientFactory);
    pPizza->setName("Chicago Style Pepperoni Pizza");
    }
    return pPizza;
    }

    int main()
    {
    PizzaStore* nyStore = new NYPizzaStore();
    PizzaStore* chicagoStore = new ChicagoPizzaStore();

    Pizza* pizza = nyStore->orderPizza(PizzaType::cheese);
    printf("Ethan ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    pizza = chicagoStore->orderPizza(PizzaType::cheese);
    printf("Joel ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    pizza = nyStore->orderPizza(PizzaType::clam);
    printf("Ethan ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    pizza = chicagoStore->orderPizza(PizzaType::clam);
    printf("Joel ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    pizza = nyStore->orderPizza(PizzaType::pepperoni);
    printf("Ethan ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    pizza = chicagoStore->orderPizza(PizzaType::pepperoni);
    printf("Joel ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    pizza = nyStore->orderPizza(PizzaType::veggie);
    printf("Ethan ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    pizza = chicagoStore->orderPizza(PizzaType::veggie);
    printf("Joel ordered a %s\n",pizza->getName().c_str());
    delete pizza;

    delete nyStore;
    delete chicagoStore;
    return 0;
    }

    运行结果如下:

    --- Making a New York Style Cheese Pizza ---
    Preparing New York Style Cheese Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Ethan ordered a New York Style Cheese Pizza
    --- Making a Chicago Style Cheese Pizza ---
    Preparing Chicago Style Cheese Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Joel ordered a Chicago Style Cheese Pizza
    --- Making a New York Style Clam Pizza ---
    Preparing New York Style Clam Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Ethan ordered a New York Style Clam Pizza
    --- Making a Chicago Style Clam Pizza ---
    Preparing Chicago Style Clam Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Joel ordered a Chicago Style Clam Pizza
    --- Making a New York Style Pepperoni Pizza ---
    Preparing New York Style Pepperoni Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Ethan ordered a New York Style Pepperoni Pizza
    --- Making a Chicago Style Pepperoni Pizza ---
    Preparing Chicago Style Pepperoni Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Joel ordered a Chicago Style Pepperoni Pizza
    --- Making a New York Style Veggie Pizza ---
    Preparing New York Style Veggie Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Ethan ordered a New York Style Veggie Pizza
    --- Making a Chicago Style Veggie Pizza ---
    Preparing Chicago Style Veggie Pizza
    Bake for 25 minutes at 350
    Cutting the pizza into diagonal slices
    Place pizza in official PizzaStore box
    Joel ordered a Chicago Style Veggie Pizza

    参考图书:《Head First 设计模式》

  • 相关阅读:
    坐火车/长途汽车去
    图书管理系统设计
    电梯演说模板练习
    敏捷开发
    团队形式
    android app demo
    classic code review
    code review
    阅读思考
    单元测试
  • 原文地址:https://www.cnblogs.com/osyun/p/2297918.html
Copyright © 2020-2023  润新知