模板方法模式Template Method,同样很简单的模式,却被非常广泛的应用。
定义:定义一个操作中的算法的骨架,而将一些具体步骤延迟到子类中实现。它使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
适用性:
一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
各子类中的公共行为应该被提取出来集中到一个公共父类中以避免代码重复。
组成:
抽象类:1.定义抽象的算法步骤接口,具体的子类将重新定义它们以实现一个算法的各个步骤。2.实现一个模板方法,定义一个算法骨架。
具体类:实现抽象类中定义的算法步骤接口。
示例代码:
//模板方法 void View::Display(){ SetFocus(); DoDisplay();//需要子类实现的算法步骤 ResetFocus(); } //DoDisplay默认实现 void DoDisplay() {} //子类重新实现接口 void MyView::DoDisplay(){ //做子类需要的逻辑 }
//示例2:
//抽象Application类的OpenDocument模板函数 void Application::OpenDocument(const char* name){ if (!CanOpenDocument(name)) return;//不能处理 Document* doc = DoCreateDocument(); if (doc){ AddDocument(doc); AboutToOpenDocument(doc); doc->Open(); doc->DoRead(); } } //其中CanOpenDocument,DoCreateDocument,AboutToOpenDocument是由Application子类实现的接口操作 而Document子类实现DoRead操作
实现该模式需要注意的问题:
1. 使用C++访问控制,模板方法本身不需要子类重写,一般定义为非虚函数。模板函数中非接口的操作,只在模板函数中调用,可以声明为保护成员。操作接口最好声明为纯虚函数。
2. 尽量减小操作接口,子类需要实现的接口越多,需要重定义的操作越多,客户程序就越冗长。
该模式应用非常广泛,相关模式有:
Factory Method工厂模式,如上面例子中的DoCreateDocument就是一个工厂函数。
Strategy策略模式:模板方法使用继承来改变算法的一部分,Strategy模式使用委托来改变整个算法。