条款22 template method 模式
template method 模式,模板方法模式 其实他和C++模板没有关系。
前者是提供的为派生类设计者提供清晰指示的一种方法,这个事实表示“如何去实现基类所规定的契约”
基类可以自由的通过公有成员函数指定与外界的契约关系,并通过受保护的成员函数为派生类的行为指明额外的细节,私有成员函数也可以用做类实现的一部分。一般数据成员应该是私有的。
如果积累的成员是非虚拟的,那么积累的设计者就为以该积累为根所确立的层次结构指明了一个不变式, 若是派生类觉得积累的同名成员无法满足要求,派生类不应该以同名的派生类成员去覆盖积累的非虚拟函数。而应该去寻找另外的积累。——因为覆盖一旦出现bug,很难查找。——要防止这种蹩脚的设计。
虚函数和纯虚函数在指定操作方面,派生类可以定制自己的实现。非纯虚函数在这方面只是提供了一个默认实现,不强求派生类去重写它。而纯虚函数则强制子类重写。
template metod 模板方法模式赋予基类一种中级的控制机制。该机制介于非虚函数和虚函数之间。template method 确立其实现的整体框架,同时将部分的实现延迟到派生类中去。通常来说,template method 被实现为一个工友的废墟函数。他调用的是被保护起来的虚函数。
派生类必须接受继承的非虚基类函数的所有实现,但同时可以重写工友函数中调用的被保护的虚函数,以有限的方式来定制其行为。
1: class App
2: {
3: public:
4: virtual ~App();
5: //..
6: void startup() // template method
7: {
8: initialize();
9: if( !validate())
10: {
11: altInit();
12: }
13: }
14: protected:
15: virtual bool validate(0 const = 0;
16: virtual void altInit();
17: //...
18: private:
19: void Initialize();
20: }
21:
22: class MyApp : public App
23: {
24: public:
25: //...
26: private:
27: bool validate() const;
28: void altInit();
29: //...
30: }
startup 函数整体流程是由积累决定,客户通过调用积累的接口来调用startup,因此客户派生类的设计者可以不用知道validate 和 altInit 何时被调用,他们只需要明确在调用这两个方法的时候,应该完成什么样的工作;基类和派生类联合做好starup的工作。