18 行为型模式-----模板方法模式

模式动机(Template Method Pattern)所谓模板,就是具有通用性的一个框架,在不同的具体环境下可以匹配不同的行为。在程序设计中,代码的复用一直是人们追求的目标,更好地利用已有的设计,不仅可以极大地提高开发效率,而且也能保证软件本身的鲁棒性。

一种代码复用的基本原则就是继承机制,但是我们也知道,普通的继承可能会造成派生类比较臃肿,具有“强制性”实现的特性,特别是基类为抽象接口时更是如此。如何让基类承担更多的一般性职责,这就是模板方法模式所解决的问题了。

在模板方法中,将算法的框架设计放在基类中定义,即基类中定义一些通用逻辑及其实现,而将可变逻辑部分留出接口等待派生类完成,这样既实现了代码的复用,又将部分具体实现权利下放到了派生类。通过模板方法,派生类可以在不更改基类中算法框架的前提下即可定制自己的特殊性。

在模板方法的实现中,有如下参与者:

抽象基类(AbstractClass):基类中定义有模板方法TemplateMethod()和基本操作PrimitiveOperation[1...n]()。模板方法调用基本操作来显示功能,基本操作具体包括如下类型:抽象操作(Abstract Operation)、具体操作(Concrete Operation)、工厂方法(Factory Method)、钩子操作(Hook Operation)。

  抽象操作:也称为原语操作,即只能被模板方法调用的操作。这种操作适合定义为protected类型,这样可以被派生类重新定义特定行为。实际中尽量减少原语操作以减轻派生  类的负担。

  具体操作:在基类中定义并实现的功能,这种操作有两种作用:其一是服务于基类中的相互调用及其语义的实现;其二是作为该类型的一般性操作被派生类复用。

  工厂方法:用于产生该类型对象中要使用的其他类型对象的一种措施,属于设计模式间的结合。在系统不是特别复杂时,该方法可以用其他方法替换。

  钩子操作:在设计类继承关系时,如果继承层次较多,我们可能会忽略对基类中的某些行为的继承,进而在派生类中又给出自己的完整实现,这样就可能会设计出比较松散的代  码结构。可以用如下设计改善:将基类中的这种操作定义为一个模板方法,在模板方法中调用一个钩子操作,而这个钩子操作最好实现为一个空操作。利用派生类重定义的钩子  行为来实现基类的模板方法,即通过派生类的具体实现来对基类进行反向控制,这也是“钩子”这个名称的来历。

具体派生类(ConcreteClass):实现基类中的特定原语操作及其钩子操作。

模式结构图:

模式代码:

bt_模板方法模式.h:

 1 #ifndef TMP_H
 2 #define TMP_H
 3 #include <iostream>
 4 using namespace std;
 5
 6 /*
 7     抽象基类
 8 */
 9 class AbstractClass
10 {
11 public:
12     virtual ~AbstractClass(){ }
13     void TemplateMethod()                   // 模板方法
14     {
15         cout << "AbstractClass::TemplateMethod()" << endl;
16         cout << "{" << endl;
17         PrimitiveOperation1();
18         PrimitiveOperation2();
19         cout << "}" << endl;
20     }
21     void ConcreteOperation()                // 具体操作
22     {
23         cout << "AbstractClass::ConcreteOperation()" << endl;
24     }
25 protected:
26     virtual void PrimitiveOperation1();     // 原语操作
27     virtual void PrimitiveOperation2() = 0; // 原语操作
28     virtual bool HookOperation() = 0;       // 钩子操作
29 };
30 void AbstractClass::PrimitiveOperation1()
31 {
32     cout << "AbstractClass::PrimitiveOperation1()" << endl;
33     if(HookOperation())
34         ConcreteOperation();
35     else
36         cout << "ConcreteClass::HookOperation() returns FALSE" << endl;
37 }
38
39 /*
40     具体派生类
41 */
42 class ConcreteClass : public AbstractClass
43 {
44 protected:
45     virtual void PrimitiveOperation2()
46     {
47         cout << "ConcreteClass Implements AbstractClass::PrimitiveOperation2()" << endl;
48     }
49     virtual bool HookOperation()
50 {
51     cout << "ConcreteClass Redefines AbstractClass::HookOperation()" << endl;
52         return true;
53     }
54 };
55
56 #endif // TMP_H

测试用例.cpp:

 1 #include "bt_模板方法模式.h"
 2
 3 int main()
 4 {
 5     AbstractClass* base = new ConcreteClass;
 6     base->TemplateMethod();
 7     delete base;
 8
 9     return 0;
10 }


如果派生类中的钩子函数返回false,那么基类中的原语操作会受到影响,这种通过派生类来反向控制基类的方式也被称为“Hollywood Principle,that is: Don’t call me,I’ll call you”,如下所示:

1 virtual bool HookOperation()
2 {
3     cout << "ConcreteClass Redefines AbstractClass::HookOperation()" << endl;
4     return false;
5 }


模式总结:

::模板方法模式在类库的设计中有着不可替代的作用,其实我们自己设计的抽象类中也经常会用到,比如抽象类中的接口合作等。

::模板方法的优势在于派生类不需要改变基类的算法框架即可重定义自己的特定部分,较之于一般的继承而言,代码复用率很高【因为一般的继承关系会覆盖基类的整个方法】。

::模板方法中钩子函数的作用很大,通过派生类特性反向控制基类的行为,实现程序结构的灵活控制。在使用模板方法模式时,限制类型最好遵循以下原则:

::在抽象基类中,不需要派生类重新设计的方法,定义为非虚方法(non-virtual)可能需要派生类重新设计的方法,定义为虚方法(virtual),并给出默认实现;必须由派生类重新  设计的方法,定义为纯虚方法(pure-virtual);当然,这些只是一般性的约定,特殊设计需要根据需求而定。

::模板方法模式使用继承来改变算法的一部分,而策略模式使用委托来改变整个算法。

时间: 2024-10-09 19:30:47

18 行为型模式-----模板方法模式的相关文章

&quot;围观&quot;设计模式(18)--行为型之模板方法模式(TemplateMethod Pattern)

模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式.让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤.----WIKIPEDIA 个人理解 模板方法模式相对而言比较简单,一般的都是由抽象类定义好模板方法,然后,子类通过继承并实现其父类中定义好的模板中需要执行的具体的方法,调用子类对象的模板方法时,会执行该类中的具体实现的方法.这个模式我个人的感觉有点像是面向过程的操作,执行完一道工序,接着下一道工序. 案例解析 模板方法相对来说比较简单,这里只列举一个例子供大

第24章 行为型模式—模板方法模式

1. 模板方法模式(Template Method Pattern)的定义 (1)定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. (2)模板方法模式的结构和说明 ①AbstractClass:抽象类.用于定义算法骨架和抽象的原语操作,具体的子类通过重定义这些原语操作来实现一个算法的各个步骤.在这个类里面,还可以提供算法中通用的实现.此外,该类还实现了一个模板方法,它定义了算法的骨架.该模板方法不仅调用原语操作,

设计模式(行为型)之模板方法模式(Template Method Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之命令模式(Command Pattern)>http://blog.csdn.net/yanbober/article/details/45500113 概述 模板方法模式是一种基于继承的代码复用,它是一种类行为型模式:是结构最简单的行为型设计模式,在其结构

行为型模式-模板方法模式

行为型模式又可以分成以下四类:第一类:通过父类与子类的关系进行实现.第二类:两个类之间.第三类:类的状态.第四类:通过中间类 模板方法模式属于第一类,父类与子类的关系 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模板类中可包含要实现的模板方法,还可以包含基本方法,基本方法分三类 (1) 抽象方法:一个抽象方法由抽象类声明.由其具体子类实现.在C#语言里一个抽象方法以abstract关键字标识. (2) 具体方法

24 种设计模式之 外观模式+模板方法模式

面向 对象的设计,外观模式和模板方法模式类似,都是封装 ,某个程序 需要很多类,而且很多地方要用. 便创建一个新的类,把拥有所有类的实例,从而使 代码简洁: 这个模式呢,有个最大的特点将细粒度的对象包装成粗粒度的对象,应用程序通过 访问这个外观对象,来完成细粒度对象的调用,外观模式一般是分布式应用和系统架构中的应用服务层的设计中常用的方式,并且一般结合外观模式+DTO 来完成服务层的设计,提供分布式应用服务的高效服务,外观模式我们可以这样理解,我们通过外观的包装,使应用程序只能看到外观对象,而不

Java设计模式之模板方法模式或者说模板设计模式(属于行为型)

抽象类,不变的代码写了,要变化的部分留给子类去实现: package 行为型_模板方法模式; //模板设计模式的意思是把不变定位部分写出来,变化的部分留给子类去实现 public abstract class GetTime { public long getTime() throws Exception{ long start = System.currentTimeMillis();//开始时间 /* //for循环 for(int i=0;i<10000;i++){ System.out.

设计模式-行为型模式-策略模式

策略模式 在实际工作中我用到了策略模式,但为什么要有环境角色呢? 这里我贴上英文对含义的介绍, The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it. 然后看看这种设计模式的组成, 一般的,策略模式

模板方法模式----你该找对象了(二)

上一篇小编叙述 模仿方法模式 模板方法模式----你该找对象了(一) 目录 1.概述 2.结构与分析 3.拓展 4.模式总结 3.拓展 钩子方法给子类留了"后门"可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制.(体现灵活性)        上篇博客续集,情侣之间约约会,看看电影,喝喝咖啡,调情调情还是不错的.说到喝咖啡,这不来到星巴克咖啡店 ,我们要了一杯咖啡,当漂亮的服务员问你:"先生,您是否要加调料?"你是呆呆地站在那--还

设计模式(行为型)之状态模式(State Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之模板方法模式(Template Method Pattern)>http://blog.csdn.net/yanbober/article/details/45501715 概述 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题.当系统中