博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
18 行为型模式-----模板方法模式
阅读量:6198 次
发布时间:2019-06-21

本文共 3408 字,大约阅读时间需要 11 分钟。

模式动机(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 
4 using namespace std; 5 6 /* 7 抽象基类 8 */ 9 class AbstractClass10 {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 else36 cout << "ConcreteClass::HookOperation() returns FALSE" << endl;37 }38 39 /*40 具体派生类41 */42 class ConcreteClass : public AbstractClass43 {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);当然,这些只是一般性的约定,特殊设计需要根据需求而定。

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

 

 

转载于:https://www.cnblogs.com/benxintuzi/p/4571373.html

你可能感兴趣的文章
易观发布《中国大件快递白皮书》德邦快递成为标准制定者
查看>>
OPPO Find X兰博基尼版到底有多受欢迎?网友:就是加价也要买
查看>>
都在讨论“无现金城市”标杆,东北三省表示:你看我们有戏么
查看>>
小牛电动递交招股书:拟募资1.5亿美元 李一男持股44%
查看>>
第十六届中博会两馆并举 展览面积16万平方米
查看>>
2019美洲杯分组出炉 巴西抽得上签 日本遭遇强敌
查看>>
四川宜宾:一男一女因悲观厌世 相约自缢死亡
查看>>
三部门整顿彩票高频快开游戏:1月16日起暂停派奖活动
查看>>
2018对啊网CPA优秀学员表彰大会暨颁奖典礼在京举行
查看>>
数据挖掘技能的分类和数据挖掘的常用方法的剖析
查看>>
最新阿里java开发岗四面:分布式+性能调优+锁+数据库等
查看>>
揭秘:阿里巴巴是如何防止信息泄露的?
查看>>
基于Kubernetes和Istio的Serverless框架Knative解析之Autoscaler
查看>>
一夜暴富的最简单方式是什么?
查看>>
经典js面试题:数组去重
查看>>
最近Android真的凉凉了?
查看>>
教你用Python动刷新抢12306火车票,附源码!
查看>>
percona toolkit 安装与使用
查看>>
chrome 插件实现mac地址获取
查看>>
深度学习和自然语言处理:诠释词向量的魅力
查看>>