定义
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把实例化推迟到子类。
要点
1)工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。
2)将创建对象的代码集中在一个对象或方法中,可以避免代码的重复,并且更方便以后的维护。这意味着客户在实例化对象时,只会依赖于接口,而不是具体的类。
3)利用工厂方法创建对象时需要扩展一个类,并覆盖他的工厂方法。
类图
PizzaStore:创建者(creator)类,这是抽象创建者。它定义了一个抽象的工厂方法,让子类实现此方法制造产品。
NYPizzaStore/ChicagoPizzaStore:能够生产产品的类,即具体创建者,每个类都实现createPizza()方法,来达到创建不同产品的目的。
Pizza:产品接口。
示例
下面实现一个披萨加盟的的模型。纽约和芝加哥各有一家披萨加盟店,他们有各自的工厂,同一款披萨会有不同的做法。
Pizza.h
#ifndef PIZZA_H
#define PIZZA_H
#include <iostream>
#include <string>
#include <list>
using namespace std;
namespace Factory {
// 披萨超类
class Pizza
{
protected:
string m_name;
string m_dough;
string m_sauce;
list<string> m_toppings;
public:
Pizza() {}
virtual ~Pizza() {}
virtual void prepare()
{
cout << "Preparing " << m_name << endl;
cout << "Tossing dough..." << endl;
cout << "Adding sauce..." << endl;
cout << "Adding toppings:" << endl;
list<string>::iterator i;
for (i=m_toppings.begin(); i!=m_toppings.end(); i++) {
cout << *i << endl;
}
}
virtual void bake()
{
cout << "Bake for 25 minutes at 350" << endl;
}
virtual void cut()
{
cout << "Cutting the pizza into diagonal slices" << endl;
}
virtual void box()
{
cout << "Place pizza in official PizzaStore box" << endl;
}
virtual string getName()
{
return m_name;
}
};
class NYStyleCheesePizza : public Pizza
{
public:
NYStyleCheesePizza()
{
this->m_name = "NY Style Sauce and Cheese Pizza";
this->m_dough = "Thin Crust Dough";
this->m_sauce = "Marinara Sauce";
this->m_toppings.push_back("Grated");
this->m_toppings.push_back("Reggiano");
this->m_toppings.push_back("Cheese");
}
};
class NYStylePepperoniPizza : public Pizza
{
public:
NYStylePepperoniPizza()
{
this->m_name = "NY Style Pepperoni Pizza";
this->m_dough = "Pepperoni Dough";
this->m_sauce = "Pepperoni Sauce";
this->m_toppings.push_back("Grated_p");
this->m_toppings.push_back("Reggiano_p");
this->m_toppings.push_back("Cheese_p");
}
};
class NYStyleClamPizza : public Pizza
{
public:
NYStyleClamPizza()
{
this->m_name = "NY Style Clam Pizza";
this->m_dough = "Clam Dough";
this->m_sauce = "Clam Sauce";
this->m_toppings.push_back("Grated_c");
this->m_toppings.push_back("Reggiano_c");
this->m_toppings.push_back("Cheese_c");
}
};
class NYStyleVeggiePizza : public Pizza
{
public:
NYStyleVeggiePizza()
{
this->m_name = "NY Style Veggie Pizza";
this->m_dough = "Veggie Dough";
this->m_sauce = "Veggie Sauce";
this->m_toppings.push_back("Grated_v");
this->m_toppings.push_back("Reggiano_v");
this->m_toppings.push_back("Cheese_v");
}
};
class ChicagoStyleCheesePizza : public Pizza
{
public:
ChicagoStyleCheesePizza()
{
this->m_name = "Chicage Style Deep Dish Cheese Pizza";
this->m_dough = "Extra Thick Crust Dough";
this->m_sauce = "Plum Tomato Sauce";
this->m_toppings.push_back("Shredded");
this->m_toppings.push_back("Mozzarella");
this->m_toppings.push_back("Cheese");
}
void cut()
{
cout << "Cutting the pizza into square slices" << endl;
}
};
}
#endif
PizzaStore.h
#ifndef PIZZASTORE_H
#define PIZZASTORE_H
#include "Pizza.h"
namespace Factory {
// 披萨商店超类
class PizzaStore
{
protected:
virtual Pizza* createPizza(string type) = 0;
public:
PizzaStore()
{}
virtual ~PizzaStore()
{}
Pizza* orderPizza(string type)
{
Pizza* pizza = createPizza(type);
pizza->prepare();
pizza->bake();
pizza->cut();
pizza->box();
return pizza;
}
};
class NYPizzaStore : public PizzaStore
{
protected:
Pizza* createPizza(string type)
{
if ("cheese" == type) {
return new NYStyleCheesePizza();
} else if ("veggie" == type) {
return new NYStyleVeggiePizza();
} else if ("clam" == type) {
return new NYStyleClamPizza();
} else if ("pepperoni" == type) {
return new NYStylePepperoniPizza();
} else {
return NULL;
}
}
};
class ChicagoPizzaStore : public PizzaStore
{
protected:
Pizza* createPizza(string type)
{
if ("cheese" == type) {
return new ChicagoStyleCheesePizza();
} else {
return NULL;
}
}
};
}
#endif
main.cpp
#include "PizzaStore.h"
using namespace Factory;
int main()
{
PizzaStore* nyStore = new NYPizzaStore();
PizzaStore* chicagoStore = new ChicagoPizzaStore();
Pizza* pizza = nyStore->orderPizza("cheese");
cout << "Ethan ordered a " << pizza->getName() << endl << endl;
pizza = chicagoStore->orderPizza("cheese");
cout << "Joel ordered a " << pizza->getName() << endl;
}
测试
测试结果如下: