定义:
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
场景:
我们的披萨商店正在加速的扩建,已经接了好多城市的加盟邀请。可是各地口味不同,如果每个地市都定义不同的披萨类型,那么后期的维护将是十分头痛的,根据分析,我们披萨的种类是固定的,变动的其实就是披萨中添加的原料类型和原料的分量,因为不同的地方所生产的原料也是不同的。所以根据总部意见,打算在各地建立一个原料工厂,制作的披萨还是那些披萨,只是各地通过自己的工厂生产披萨的原料,加入到自己的披萨当中,这样,虽然生产的流程不变,但是最终的披萨口味确实符合了当地人民的需求。我们的披萨商店现在可以放心的到处开分店啦。
类图:
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 设计模式》