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