1、Template Method模式(模版方法)模式和C++模版一点关系都没有。
前者是基类设计者为派生类设计者提供清晰指示的一种方式,这个指示就是“应该如何实现基类所规定的契约”。
基类可以自由的通过其公有成员函数指定与外界的契约关系,并通过受保护的成员函数为派生类指明额外的细节。
私有成员函数也可以用作类实现的一部分。数据成员应该指定为私有。
2、一个基类的成员函数是否应该为非虚拟的、虚拟的或纯虚拟的,这样的决策主要是基于该函数的行为如何被派生类定制。
毕竟,使用基类接口的代码并不关心对象是怎么实现一个特定操作的,它只关心对一个对象执行该操作,而恰当地实现该操作则是对象自己的事情。
如果基类成员是非虚拟的,那么基类设计者就为以该基类为根所确立的层次结构指明了一个不变式。
派生类不应该用同名的派生类成员去隐藏基类非虚函数。
如果不喜欢基类所指定的契约,可以去寻找另一个合乎心意的基类,而不要试图去改写基类的契约。
3、虚函数和纯虚函数指定的操作,其实现可以由派生类通过重写机制定制。
一个非纯虚的函数提供了一个默认实现,并且不强求派生类一定要重写它,而一个纯虚函数则必须在具体派生类(即非抽象的派生类)中进行重写。
这两种虚函数都允许派生类插入并取代其整个实现,同时保持接口不变。
4、Template Method模式赋予基类设计者一种中级控制机制,该控制机制介于非虚函数提供的“占有它或离开它”和虚函数提供的“如果你不喜欢就替换掉所有东西”这两种机制之间。
Template Method确立了其实现的整体架构,同时将部分实现延迟到派生类中进行。
通常来说,Template Method被实现为一个公有非虚函数,它调用被保护的虚函数。
派生类必须接收受它所继承的非虚基类函数所指明的全部实现,同时还可以通过重写该公有函数所调用的被保护的虚函数,以有限的方式来定制其行为。
class App {
public:
virtual ~App( );
//....
void startup( ) { //Template Method
initialize( );
if( !validate( ) )
altInit( );
}
protect:
virtual bool validate( ) const = 0;
virtual void altInit( );
//...
private:
void initialize( );
//...
};
非虚拟的startup Template Method可以向下调用派生类提供的定制实现:
class MyApp( ) : public App {
public:
//....
private:
bool validate( ) const;
void altInit( );
//...
};
5、Template Method是一个“好莱坞法则”的例子,即“不要call我们,我们会call你”(参见博客十九)。
startup函数的整体流程由基类决定,客户通过基类的接口来调用startup,因此派生类设计者不知道validate或altInit何时会被调用。
但他们知道当这连个方法被调用时,它们各自应该做什么。因此我们说,基类和派生类合力打造了一个完整的函数实现。