定义:
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类。
场景:
接简单工厂模式。现在我们纽约的披萨工厂已经转入正轨,我们打算再芝加哥再开一家披萨商店,但是两个地区的人们对于披萨要求的口味各不相同,所以我们需要依据各地的顾客的口味添加不同的原料来制作当地人民喜欢吃的披萨。所以我们用芝加哥商店和纽约商店分别制造属于当地口味的披萨。
类图:
c++代码如下:
#include <iostream> #include <vector> using namespace std; class PizzaType { public: enum EPizzaType {cheese,veggie,clam,pepperoni}; enum EPizzaStyle {NY,Chicago}; }; class Pizza { public: virtual ~Pizza() {}; void prepare(); virtual void bake(); virtual void cut(); virtual void box(); string getName(); protected: string m_sName; string m_sDough; string m_sSauce; vector<string> m_vToppings; }; class NYStyleCheesePizza : public Pizza { public: NYStyleCheesePizza(); }; class NYStyleClamPizza : public Pizza { public: NYStyleClamPizza(); }; class NYStylePepperoniPizza : public Pizza { public: NYStylePepperoniPizza(); }; class NYStyleVeggiePizza : public Pizza { public: NYStyleVeggiePizza(); }; class ChicagoStyleCheesePizza : public Pizza { public: ChicagoStyleCheesePizza(); void cut(); }; class ChicagoStyleClamPizza : public Pizza { public: ChicagoStyleClamPizza(); void cut(); }; class ChicagoStylePepperoniPizza : public Pizza { public: ChicagoStylePepperoniPizza(); void cut(); }; class ChicagoStyleVeggiePizza : public Pizza { public: ChicagoStyleVeggiePizza(); void cut(); }; class PizzaStore { public: virtual Pizza* createPizza(PizzaType::EPizzaType type) = 0; Pizza* orderPizza(PizzaType::EPizzaType type); }; class NYPizzaStore : public PizzaStore { public: Pizza* createPizza(PizzaType::EPizzaType type); }; class ChicagoPizzaStore : public PizzaStore { public: Pizza* createPizza(PizzaType::EPizzaType type); }; class DependentPizzaStore { public: Pizza* createPizza(PizzaType::EPizzaStyle style, PizzaType::EPizzaType type); }; void Pizza::prepare() { printf("Preparing %s\n",m_sName.c_str()); printf("Tossing dough %s\n",m_sDough.c_str()); printf("Adding sauce %s\n",m_sSauce.c_str()); printf("Adding toppings: "); for (unsigned int i=0; i<m_vToppings.size(); ++i) { printf(" %s",m_vToppings.at(i).c_str()); } printf("\n"); } 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; } NYStyleCheesePizza::NYStyleCheesePizza() { m_sName = "NY Style Sauce and Cheese Pizza"; m_sDough = "Thin Crust Dough"; m_sSauce = "Marinara Sauce"; m_vToppings.push_back("Grated Reggiano Cheese"); } NYStyleClamPizza::NYStyleClamPizza() { m_sName = "NY Style Clam Pizza"; m_sDough = "Thin Crust Dough"; m_sSauce = "Marinara Sauce"; m_vToppings.push_back("Grated Reggiano Cheese"); m_vToppings.push_back("Fresh Clams from Long Island Sound"); } NYStylePepperoniPizza::NYStylePepperoniPizza() { m_sName = "NY Style Pepperoni Pizza"; m_sDough = "Thin Crust Dough"; m_sSauce = "Marinara Sauce"; m_vToppings.push_back("Grated Reggiano Cheese"); m_vToppings.push_back("Sliced Pepperoni"); m_vToppings.push_back("Garlic"); m_vToppings.push_back("Onion"); m_vToppings.push_back("Mushrooms"); m_vToppings.push_back("Red Pepper"); } NYStyleVeggiePizza::NYStyleVeggiePizza() { m_sName = "NY Style Veggie Pizza"; m_sDough = "Thin Crust Dough"; m_sSauce = "Marinara Sauce"; m_vToppings.push_back("Grated Reggiano Cheese"); m_vToppings.push_back("Garlic"); m_vToppings.push_back("Onion"); m_vToppings.push_back("Mushrooms"); m_vToppings.push_back("Red Pepper"); } ChicagoStyleCheesePizza::ChicagoStyleCheesePizza() { m_sName = "Chicago Style Deep Dish Cheese Pizza"; m_sDough = "Extra Thick Crust Dough"; m_sSauce = "Plum Tomato Sauce"; m_vToppings.push_back("Shredded Mozzarella Cheese"); } void ChicagoStyleCheesePizza::cut() { printf("Cutting the pizza into square slices\n"); } ChicagoStyleClamPizza::ChicagoStyleClamPizza() { m_sName = "Chicago Style Clam Pizza"; m_sDough = "Extra Thick Crust Dough"; m_sSauce = "Plum Tomato Sauce"; m_vToppings.push_back("Shredded Mozzarella Cheese"); m_vToppings.push_back("Frozen Clams from Chesapeake Bay"); } void ChicagoStyleClamPizza::cut() { printf("Cutting the pizza into square slices\n"); } ChicagoStylePepperoniPizza::ChicagoStylePepperoniPizza() { m_sName = "Chicago Style Pepperoni Pizza"; m_sDough = "Extra Thick Crust Dough"; m_sSauce = "Plum Tomato Sauce"; m_vToppings.push_back("Shredded Mozzarella Cheese"); m_vToppings.push_back("Black Olives"); m_vToppings.push_back("Spinach"); m_vToppings.push_back("Eggplant"); m_vToppings.push_back("Sliced Pepperoni"); } void ChicagoStylePepperoniPizza::cut() { printf("Cutting the pizza into square slices\n"); } ChicagoStyleVeggiePizza::ChicagoStyleVeggiePizza() { m_sName = "Chicago Deep Dish Veggie Pizza"; m_sDough = "Extra Thick Crust Dough"; m_sSauce = "Plum Tomato Sauce"; m_vToppings.push_back("Shredded Mozzarella Cheese"); m_vToppings.push_back("Black Olives"); m_vToppings.push_back("Spinach"); m_vToppings.push_back("Eggplant"); } void ChicagoStyleVeggiePizza::cut() { printf("Cutting the pizza into square slices\n"); } Pizza* PizzaStore::orderPizza(PizzaType::EPizzaType type) { Pizza* pizza = createPizza(type); printf("--- Making a %s ---\n" ,pizza->getName().c_str()); pizza->prepare(); pizza->bake(); pizza->cut(); pizza->box(); return pizza; } Pizza* NYPizzaStore::createPizza(PizzaType::EPizzaType type) { if (PizzaType::cheese == type) { return new NYStyleCheesePizza(); } else if (PizzaType::veggie == type) { return new NYStyleVeggiePizza(); } else if (PizzaType::clam == type) { return new NYStyleClamPizza(); } else if (PizzaType::pepperoni == type) { return new NYStylePepperoniPizza(); } return NULL; } Pizza* ChicagoPizzaStore::createPizza(PizzaType::EPizzaType type) { if (PizzaType::cheese == type) { return new ChicagoStyleCheesePizza(); } else if (PizzaType::veggie == type) { return new ChicagoStyleVeggiePizza(); } else if (PizzaType::clam == type) { return new ChicagoStyleClamPizza(); } else if (PizzaType::pepperoni == type) { return new ChicagoStylePepperoniPizza(); } return NULL; } Pizza* DependentPizzaStore::createPizza(PizzaType::EPizzaStyle style, PizzaType::EPizzaType type) { Pizza* pizza = NULL; if (PizzaType::NY == style) { if (PizzaType::cheese == type) { pizza = new NYStyleCheesePizza(); } else if (PizzaType::veggie == type) { pizza = new NYStyleVeggiePizza(); } else if (PizzaType::clam == type) { pizza = new NYStyleClamPizza(); } else if (PizzaType::pepperoni == type) { pizza = new NYStylePepperoniPizza(); } } else if (PizzaType::Chicago == style) { if (PizzaType::cheese == type) { pizza = new ChicagoStyleCheesePizza(); } else if (PizzaType::veggie == type) { pizza = new ChicagoStyleVeggiePizza(); } else if (PizzaType::clam == type) { pizza = new ChicagoStyleClamPizza(); } else if (PizzaType::pepperoni == type) { pizza = new ChicagoStylePepperoniPizza(); } } pizza->prepare(); pizza->bake(); pizza->cut(); pizza->box(); return pizza; } int main() { NYPizzaStore nyStore; ChicagoPizzaStore chicagoStore; Pizza* pizza = NULL; 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; return 0; }
运行结果如下:
--- Making a NY Style Sauce and Cheese Pizza ---
Preparing NY Style Sauce and Cheese Pizza
Tossing dough Thin Crust Dough
Adding sauce Marinara Sauce
Adding toppings: Grated Reggiano Cheese
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a NY Style Sauce and Cheese Pizza
--- Making a Chicago Style Deep Dish Cheese Pizza ---
Preparing Chicago Style Deep Dish Cheese Pizza
Tossing dough Extra Thick Crust Dough
Adding sauce Plum Tomato Sauce
Adding toppings: Shredded Mozzarella Cheese
Bake for 25 minutes at 350
Cutting the pizza into square slices
Place pizza in official PizzaStore box
Joel ordered a Chicago Style Deep Dish Cheese Pizza
--- Making a NY Style Clam Pizza ---
Preparing NY Style Clam Pizza
Tossing dough Thin Crust Dough
Adding sauce Marinara Sauce
Adding toppings: Grated Reggiano Cheese Fresh Clams from Long Island Sound
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a NY Style Clam Pizza
--- Making a Chicago Style Clam Pizza ---
Preparing Chicago Style Clam Pizza
Tossing dough Extra Thick Crust Dough
Adding sauce Plum Tomato Sauce
Adding toppings: Shredded Mozzarella Cheese Frozen Clams from Chesapeake Ba
y
Bake for 25 minutes at 350
Cutting the pizza into square slices
Place pizza in official PizzaStore box
Joel ordered a Chicago Style Clam Pizza
--- Making a NY Style Pepperoni Pizza ---
Preparing NY Style Pepperoni Pizza
Tossing dough Thin Crust Dough
Adding sauce Marinara Sauce
Adding toppings: Grated Reggiano Cheese Sliced Pepperoni Garlic Onion
Mushrooms Red Pepper
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a NY Style Pepperoni Pizza
--- Making a Chicago Style Pepperoni Pizza ---
Preparing Chicago Style Pepperoni Pizza
Tossing dough Extra Thick Crust Dough
Adding sauce Plum Tomato Sauce
Adding toppings: Shredded Mozzarella Cheese Black Olives Spinach Eggpla
nt Sliced Pepperoni
Bake for 25 minutes at 350
Cutting the pizza into square slices
Place pizza in official PizzaStore box
Joel ordered a Chicago Style Pepperoni Pizza
--- Making a NY Style Veggie Pizza ---
Preparing NY Style Veggie Pizza
Tossing dough Thin Crust Dough
Adding sauce Marinara Sauce
Adding toppings: Grated Reggiano Cheese Garlic Onion Mushrooms Red Pe
pper
Bake for 25 minutes at 350
Cutting the pizza into diagonal slices
Place pizza in official PizzaStore box
Ethan ordered a NY Style Veggie Pizza
--- Making a Chicago Deep Dish Veggie Pizza ---
Preparing Chicago Deep Dish Veggie Pizza
Tossing dough Extra Thick Crust Dough
Adding sauce Plum Tomato Sauce
Adding toppings: Shredded Mozzarella Cheese Black Olives Spinach Eggpla
nt
Bake for 25 minutes at 350
Cutting the pizza into square slices
Place pizza in official PizzaStore box
Joel ordered a Chicago Deep Dish Veggie Pizza
参考图书:《Head First 设计模式》