【转】设计模式学习笔记(3)-工厂方法
目的:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类
怎样理解这句话呢?在程序编写中为了实现代码的复用,我们往往会采用继承的方式来完成。设计一个父类,父类中有一些公用的方法可以提供给子类使用,但子类往往差距较大,这时我们在父类会采用
一种虚构造器(Vitual Constructor),即工厂方法来实现。
举个例子,我们有一个面包生产流水线,这涉及到两个部分:面包的生产与包装。不同面包的包装流程往往是相同的,但制作工艺却差距
巨大,黑面包和白面包采用的原料肯定是不一样的。这种情况下怎么办呢?流水线要工作离不开面包的生产啊,但面包的生产又涉及到子类具体的实现。我们想到能否让具体面包的初始化延迟到子类呢?
这实际上就是懒加载(Lazy load)
这里Bread是抽象类,它有两个子类:WhiteBread和BlackBread。BreadFactory也是抽象类,其中createBread方法是纯虚函数,必须由子类来实现,它的两个子类是WhiteBreadFactory和BlackBreadFactory。
我们可以简单地看一下他们的代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Bread{public : virtual void color() = 0;};class WhiteBread : public Bread{public: void color() { cout << "this bread is white!" << endl; }};class BlackBread : public Bread{ void color() { cout << "this bread is black!" << endl; }}; |
我们在面板类中定义了color方法以返回面包的颜色
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
class BreadFactory{public: virtual Bread* createBread() = 0; virtual void wrapBread(Bread* bread) { cout << "I'm wrapping the bread; " << bread->color(); } virtual void go() { this->wrapBread(this->createBread()); }};class WhiteBreadFactory : public BreadFactory{public: Bread* createBread() { return new WhiteBread; }};class BlackBreadFactory : public BreadFactory{public: Bread* createBread() { return new BlackBread; }}; |
在工厂方法中调用go方法可以实现面包的生成和打包,而面包的生成全部下放到具体子类来实现。我们在主方法中写道:
|
1
2
|
BreadFactory* factory = new WhiteBreadFactory();factory->go(); |
最终屏幕输出为:
|
1
|
I'm wrapping the bread this bread is white! |
如果我们要生成黑面包只需将代码改为下面这样就行了。
|
1
|
BreadFactory* factory = new BlackBreadFactory(); |
我们来回顾一下刚刚发生了什么。我们新建了一个抽象工厂,由其子类WhiteBreadFactory来实例化。当我们调用factory->go()时,程序会调用BreadFactory中的go方法,发现其是一个纯虚函数,于是寻找其实现
类中的方法,实现类返回了一个WhiteBread对象,于是程序继续执行到wrapBread方法,wrapBread方法是一个虚函数(不是必须的),在子类中没有重载,于是执行父类的wrapBread函数。最终打印结果。
利用工厂方法模式我们能做些什么呢?
当我们添加新的面包如YellowBread时,只需添加一个YellowBread实现类和一个工厂类即可。如果我们想在createBread方法中添加一些新的内容如加黄油等等只需在子类中编写就行了。这种改变十分灵活,而且有个专业术语叫做:钩子(hook)。
GoF还提到了一个概念:平行的类层次。是指如果一个类将它的一些职责委托给一个独立的类的时候,便产生了平行类层次。如本例中WhiteBread和WhiteBreadFactory就是一个平行的类,BlackBread和BlackBreadFactory也是一个平行的类层次。
而工厂方法模式为连接了平行的类层次,使得类的责任分工明确。
如果仔细看我们的代码,会发现有些重复:BlackBreadFactory和WhiteBreadFactory只有返回值不同。很自然地我们想到可以采用C++等语言提供的模版机制来消除重复。
|
1
2
3
4
5
6
7
8
9
|
templateclass NewBreadFactory : public BreadFactory{public: T* createBread() { return new T; }}; |
在主方法中这样写:
|
1
|
BreadFactory* factory = new NewBreadFactory(); |
输出结果是一样的。这样以后添加新的面包只需编写继承Bread类的子类就行了。
惯例我们看看工厂方法模式的适用性:
- 当一个类不知道它所创建的对象的类的时候
- 当一个类希望由它的子类来指定它所创建的对象的时候
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理这这一信息局部化的时候
工厂方法模式和前面所说的抽象工厂模式有什么联系和区别呢?抽象工厂模式使用了工厂方法模式,工厂方法模式更普遍一点,两者并不存在冲突。
原文链接:http://lecoding.com/articles/93.html
posted on 2013-03-05 13:45 TheKingOfKingFish 阅读(126) 评论(0) 收藏 举报

浙公网安备 33010602011771号