原文连接 http://blog.csdn.net/myan/archive/2001/06/02/1909.aspx
设计模式:template method
以下是该文中的一份示例代码
class Mountie {
public:
void read( std::istream & );
void write( std::ostream & ) const;
virtual ~Mountie();
protected:
virtual void do_read( std::istream & );
virtual void do_write( std::ostream & ) const;
private:
virtual std::string classID() const = 0;
}
void Mountie::write(std::ostream &Dudley) const
{
Dudley << classID() << std::endl;
do_write(Dudley);
}
代码非常简短,但是每一行都透出精深功力,奈人寻味。原文中就为何对类中的成员函数实施的三种不同的控制级别进行了非常精彩的阐述。
我想从另一个方面谈谈我对这份代码的一些感悟,跟大家一起讨论讨论。
1.该类中的两个非虚拟的模板方法
我们知道template method是将整个继承体系(class hierarchy)当中的一些恒定不变的算法,或者说是流程,提炼成一个模板方法,放置在顶层类中,以便实现在整个class
hierarchy中复用该模板,防止相同的代码在整个class hierarchy中扩散。 既然该算法是恒定不变的,让我们回想一下Scott Meyers在《effective c++》中为非虚拟函数的最核
心的本质进行的归纳:不变性凌驾于变异性之上。整个继承体系中,该模板算法恒定不变,任何子类都不能重载该函数。
2.两个虚拟函数
理解了上面一点之后,两个虚函数就非常好理解了,整个模板方法的实施框架是恒定不变的,但框架中每一步的具体作法却可以张三李四各不相同,作为模板方法中的一部分,子
类可以重载也可以不重载模板方法内部的一些子流程,子方法,不变中又蕴涵着千变万化,十分灵活。
3.一个纯虚函数
纯虚函数是子类必须要实现的函数,和非虚拟函数恰恰是两个极端:变异性凌驾于不变性之上,每个派生类的中独一无二的实现细节必须要重载该函数。
-----------------------------------------------
整个模式以不变为根本,从不变开始,以求变为核心,在变与不变中,实现了父类对子类的完整约束,这种约束机制非常灵活,也非常强大,大师们通过约束子类不变,可变以及
必须变,可以做到对派生类的精确控制,收放自如,这种境界确实非一般人能达到啊。Andrei Alexandrescu在《Modern c++ design》中说:“一个良好的设计应该在编译期表现
出大部分constraints(约束条件,规范)”,优秀的程序员善于利用语言强大的语法对自己的代码进行最大限度约束,利用“编译防火墙”避免让自己走入错误的阴暗角落。