1. 场景
假设有如下的场景:
卖pizza的, 可以有很多种pizza(CheesePizza, GreekPizza, PepperoniPizza),我们该如何处理它呢,当然我们可以声明一个类,类中创建每一个种类的pizza。但是这样有什么问题吗?我们没有把需要改变的部分剥离出来。软件设计的一个原则就是“是易于扩充而不是修改”,另一个是“对接口编程而不是对实现编程”。
这里就轮到工厂模式出手了。 工厂模式有三种:
- 简单工厂
- 抽象工厂
- 工厂方法
2. 简单工厂模式
1.1 Uml
1.2 源代码
class Pizza { public: Pizza(){}; virtual ~Pizza(){}; virtual void MakePizza() = 0; }; class CheesePizza : public Pizza { public: CheesePizza(){}; ~CheesePizza(){}; void MakePizza() { cout << "make cheese pizza" <<endl; } }; class GreekPizza : public Pizza { public: GreekPizza(){}; ~GreekPizza(){}; void MakePizza() { cout << "make greek pizza" <<endl; } }; class PepperoniPizza : public Pizza { public: PepperoniPizza(){}; ~PepperoniPizza(){}; void MakePizza() { cout << "make peperoni pizza" <<endl; } }; enum PIZZA_TYPE { PIZZA_TYPE_CHEESE = 0, PIZZA_TYPE_GREEK, PIZZA_TYPE_PEPPERONI }; class PizzaFactory { public: PizzaFactory(){}; ~PizzaFactory(){}; static shared_ptr<Pizza> createPizza(PIZZA_TYPE pizzaType) { switch (pizzaType) { case PIZZA_TYPE_CHEESE: return shared_ptr<Pizza>(new CheesePizza()); case PIZZA_TYPE_GREEK: return shared_ptr<Pizza>(new GreekPizza()); case PIZZA_TYPE_PEPPERONI: return shared_ptr<Pizza>(new PepperoniPizza()); default: return shared_ptr<Pizza>(new PepperoniPizza()); } } };
测试代码
int _tmain(int argc, _TCHAR* argv[]) { shared_ptr<Pizza> cheesePizza = PizzaFactory::createPizza(PIZZA_TYPE_CHEESE); shared_ptr<Pizza> greekPizza = PizzaFactory::createPizza(PIZZA_TYPE_GREEK); shared_ptr<Pizza> pepperoniPizza = PizzaFactory::createPizza(PIZZA_TYPE_PEPPERONI); cheesePizza->MakePizza(); greekPizza->MakePizza(); pepperoniPizza->MakePizza(); return 0; }
这样写好什么好处呢?
- .静态工厂方法统一管理对象的创建
- 静态工厂方法推迟了产品的实例化。
这样写的缺点是什么呢?
缺点就是在增加新的类型时,需要修改工厂类。这违反了开放封闭原则:软件实体(类、模块、函数)可以扩展,但是不可修改。于是需要更高级的工厂方法模式。
2. 工厂方法模式
工厂方法模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
当然从代码的角度就是其实就是把 PizzaFactory 抽象出来,用子类来实现。
class PizzaFactory { public: PizzaFactory(){}; ~PizzaFactory(){}; virtual Pizza* createPizza() = 0; }; class PizzaFactoryCheese : public PizzaFactory { public: CheesePizza* createPizza() { return new CheesePizza; } } class PizzaFactoryGreek : public PizzaFactory { public: GreekPizza* createPizza() { return new GreekPizza; } }
注意:由于此时PizzaFactory的createPizza()为虚函数,因此不能使用static修饰符。
工厂方法模式也有缺点,每增加一种产品,就需要增加一个对象的工厂。显然,相比简单工厂模式,工厂方法模式需要更多的类定义。
至此,貌似有简单工厂模式和工厂方法模式所有问题都可以应付了,但是,如果生意扩大了,除了Pizza又做Hamburger了,怎么办? 于是抽象工厂模式出现了。
3. 抽象工厂
抽象工厂和工厂方法的主要区别是工厂方法使用继承来创建对象,而抽象工厂是使用组合。
例子代码如下:
class Burger { public: Burger(){}; virtual ~Burger(){}; virtual void MakeBurger() = 0; }; class KfcBurger : public Burger { public: KfcBurger (){}; ~KfcBurger (){}; void MakeBurger() { cout << "make KFC Burget" <<endl; } }; class McdBurger : public Burger { public: McdBurger (){}; ~McdBurger (){}; void MakeBurger() { cout << "make McD Burget" <<endl; } }; class CoreFactory { virtual Pizza* MakePizza() = 0; virtual Burger* MakeBurger() = 0; } class FactoryA : public CoreFactory { public: Pizza* MakePizza() {return new CheesePizza;} Burger* MakeBurger() {return new KfcBurger;} } class FactoryB : public CoreFactory { public: Pizza* MakePizza() {return new GreekPizza;} Burger* MakeBurger() {return new McdBurger;} }