C++设计模式之模板方法模式

2015-02-18  来源:本站原创  分类:C 语言  人气:0 

这篇文章主要介绍了C++设计模式之模板方法模式,本文讲解了什么是模板方法模式、模板方法模式的UML类图、模板方法模式的使用场合等内容,需要的朋友可以参考下

前言

离开了自己工作了将近两年的公司,日子不再有了忙碌,可以闲下来,躺在家里的床上,想着以后的路怎么走,说实话,真的很迷茫,从2012年毕业到现在,时间不长,但是学到的东西真的是非常有限,一直从事于Windows平台上的开发。说到Windows平台的开发,大家都肯定知道的HOOK的,即使不知道HOOK,对于COM应该也是知道的,我的系列博文中也对COM进行过全面的总结。说白了,HOOK就是在执行某个功能时,会有一个一系列的执行过程,对于这个过程一般都是固定的,比如:第一步执行什么,第二步干什么,最后一步干什么,都是设计好的。而具体如何去完成每一步,都是可以由程序员去控制的。COM也是如此,COM是面对接口的,当完成某一个功能模块时,就可能是系列接口的叠加调用,而接口的实现都是由程序员来控制的。说白了,一个功能模块的实现流程是固定了,但是对于每一步的具体实现都是不固定的。对于这种需求,一般是如何来做的呢?从设计模式的角度来说,这个设计模式叫模板方法模式,可能你不知道这个设计模式的名字,但是,这种方法你已经用过了。现在我就对模板方法模式进行详细的总结。

模板方法模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中对模板方法模式是这样说的:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。TemplateMethod使得子类可以不改变一个算法的接口即可重定义改算法的某些特定步骤。

我结合我在实际开发项目中的一个例子来说说这个模板方法模式吧。我们曾经做过一款产品,这个产品类似于一个云端的文件管理客户端。对于这样的一个客户端,由于其云端的服务器有三种,而每一种服务器之间的通信方式和对外公开的接口都是不是一致的,这就需要实现的客户端要屏蔽云端服务器和接口的差异性,而提供统一的操作界面,所以在实现这个客户端的同时,我们实现了一个框架,一个对于服务器和接口是通用的框架,比如就拿文件下载来说说。我们的实现大概如下:

class FileOperation

{

public:

     bool DownloadFile(wchar_t *pSrc, wchar_t *pDest)

     {

          if (!pSrc || !pDest) return false;

          if (!DoBeginDownloadFile(pSrc, pDest)) return false;

          if (!DoDownloadFile(pSrc, pDest)) return false;

          if (!DoEndDownloadFile(pSrc, pDest)) return false;

     }

protected:

     virtual bool DoBeginDownloadFile(wchar_t *pSrc, wchar_t *pDest);

     virtual bool DoDownloadFile(wchar_t *pSrc, wchar_t *pDest);

     virtual bool DoEndDownloadFile(wchar_t *pSrc, wchar_t *pDest);

};

class HttpFileOperation : public FileOperation

{

protected:

     virtual bool DoBeginDownloadFile(wchar_t *pSrc, wchar_t *pDest);

     virtual bool DoDownloadFile(wchar_t *pSrc, wchar_t *pDest);

     virtual bool DoEndDownloadFile(wchar_t *pSrc, wchar_t *pDest);

};

class SOAPFileOperation : public FileOperation

{

protected:

     virtual bool DoBeginDownloadFile(wchar_t *pSrc, wchar_t *pDest);

     virtual bool DoDownloadFile(wchar_t *pSrc, wchar_t *pDest);

     virtual bool DoEndDownloadFile(wchar_t *pSrc, wchar_t *pDest);

};

下载文件的流程为:先调用DoBeginDownloadFile,执行下载文件之前的一些操作,再调用DoDownloadFile实现真正的文件下载,最后调用DoEndDownloadFile完成文件下载的清理工作。对于任何服务器,下载文件的这个流程是不会发生变化的。而在DoBeginDownloadFile、DoDownloadFile和DoEndDownloadFile的内部具体是如何实现的,由程序员根据具体的云端服务器和对外公开的接口来完成的。最终客户端去完成文件下载操作时,只会调用DownloadFile函数就可以完成。可以看到,在上面的代码中,只有DownloadFile是public的,其它的操作函数都是protected。这也意味着,我们完成的框架对外只公开DownloadFile接口。

UML类图

C++设计模式之模板方法模式

AbstractClass(抽象类):定义抽象的原语操作,具体的子类将重定义它们以实现一个算法的各步骤。主要是实现一个模板方法,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。
ConcreteClass(具体类):实现原语操作以完成算法中与特定子类相关的步骤。
由于在具体的子类ConcreteClass中重定义了实现一个算法的各步骤,而对于不变的算法流程则在AbstractClass的TemplateMethod中完成。

使用场合

模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。在使用模板方法时,很重要的一点是模板方法应该指明哪些操作是可以被重定义的,以及哪些是必须被重定义的。要有效的重用一个抽象类,子类编写者必须明确了解哪些操作是设计为有待重定义的。

代码实现

这里就根据上面的类图,对模板方法模式进行了简单的实现。由于该模式非常简单,所以也没有更多的可以讲的了。

复制代码 代码如下:

#include <iostream>

using namespace std;

class AbstractClass

{

public:

     void TemplateMethod()

     {

          PrimitiveOperation1();

          cout<<"TemplateMethod"<<endl;

          PrimitiveOperation2();

     }

protected:

     virtual void PrimitiveOperation1()

     {

          cout<<"Default Operation1"<<endl;

     }

     virtual void PrimitiveOperation2()

     {

          cout<<"Default Operation2"<<endl;

     }

};

class ConcreteClassA : public AbstractClass

{

protected:

          virtual void PrimitiveOperation1()

     {

          cout<<"ConcreteA Operation1"<<endl;

     }

     virtual void PrimitiveOperation2()

     {

          cout<<"ConcreteA Operation2"<<endl;

     }

};

class ConcreteClassB : public AbstractClass

{

protected:

          virtual void PrimitiveOperation1()

     {

          cout<<"ConcreteB Operation1"<<endl;

     }

     virtual void PrimitiveOperation2()

     {

          cout<<"ConcreteB Operation2"<<endl;

     }

};

int main()

{

     AbstractClass *pAbstractA = new ConcreteClassA;

     pAbstractA->TemplateMethod();

     AbstractClass *pAbstractB = new ConcreteClassB;

     pAbstractB->TemplateMethod();

     if (pAbstractA) delete pAbstractA;

     if (pAbstractB) delete pAbstractB;

}

总结

模板方法模式,总的来说很好接受,很好理解,没有难点;对于此设计模式,我个人觉的还是可以和装饰模式进行对比一下。还是有一些相似之处的。好了,该设计模式的讲解就到此结束。

相关文章
  • C++设计模式之模板方法模式 2015-02-18

    这篇文章主要介绍了C++设计模式之模板方法模式,本文讲解了什么是模板方法模式.模板方法模式的UML类图.模板方法模式的使用场合等内容,需要的朋友可以参考下 前言 离开了自己工作了将近两年的公司,日子不再有了忙碌,可以闲下来,躺在家里的床上,想着以后的路怎么走,说实话,真的很迷茫,从2012年毕业到现在,时间不长,但是学到的东西真的是非常有限,一直从事于Windows平台上的开发.说到Windows平台的开发,大家都肯定知道的HOOK的,即使不知道HOOK,对于COM应该也是知道的,我的系列博文中

  • 设计模式学习笔记(十六)--Template Method模板方法模式 2014-11-14

    今天开始学习设计模式中的第三个类型--行为型模式. 行为模式: 行为型模式涉及到算法和对象间职责的分配.将注意力从控制流转移到对象间的联系方式上来. 行为模式分为:行为类模式和行为对象模式.行为类模式使用继承机制在类间分派行为:行为对象模式使用对象复合而不是继承. Template Method模板方法模式 Template Method模板方法模式介绍: Template Method模板方法模式是一种行为型模式,具体点说是行为类型模式.主要解决在软件构建过程中,对于某一项任务,常常有稳定的整

  • 设计模式之行为模式(2)-命令,迭代器,中介者,观察者,模板方法 2013-12-12

    1 命令模式 对每个执行请求进行封装. interface Command { void execute(); }; class OpenCommand : Command { void execute() { // open file } } class CloseCommand : Command { void execute() { // close file } } // 菜单项实体与执行过程的解耦 class MenuItem { string m_caption; Command m

  • 设计模式--模板方法模式 2014-01-08

    定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变算法结构的情况下,重新定义算法中的某些步骤. 注意:如果某些步骤是可选的,那么可以引入"钩子"方法作为判断条件,是否执行某些可选步骤."钩子"不是必要的. 模板 ?,一个方法,算法的一组步骤(一组子方法,其中任何子步骤都可以抽象,由子类实现(primitiveOperation),或者部分方法(concreteOperation,一般为final类型)在基类实现),这样确保算法

  • 深入理解JavaScript系列(41):设计模式之模板方法详解 2014-07-11

    这篇文章主要介绍了深入理解JavaScript系列(41):设计模式之模板方法详解,模板方法(TemplateMethod)定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤,需要的朋友可以参考下 介绍 模板方法(TemplateMethod)定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模板方法是一种代码复用的基本技术,在类库中尤为重要

  • 行为型模式:Template Method 模板方法模式 2011-04-24

    行为型模式:Template Method 模板方法模式 1.无处不在的Template Method 1)如果你只想掌握一种设计模式,那么它就是Template Method模式! 2)变与不变 变化--是软件设计的永恒主题,如何管理变化带来的复杂性?设计模式的艺术和复杂度就在于如何分析,并发现系统中的变化点和稳定点,并使用特定的设计方法来应对这种变化. 2.动机(Motivation) 1)在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于

  • (九)模板方法模式详解(包含与类加载器不得不说的故事) 2015-02-02

    模板方法模式,这是一个在许多优秀的开源项目中LZ见的最多的一个设计模式,也是LZ觉得最为优秀的一个设计模式,所以这一章LZ会尽自己所能的去尽量将这个设计模式解释清楚. 模板方法模式,一般是为了统一子类的算法实现步骤,所使用的一种手段或者说是方式.它在父类中定义一系列算法的步骤,而将具体的实现都推迟到子类. 最典型的形式就是一个接口,一个抽象父类,父类中会有一系列的抽象方法,而在子类中去一一实现这些方法. 下面LZ给举一个例子,比如我们有一个接口,里面就一个方法,是用来制造一个HTML页面,如下.

  • 23种Java设计模式(4)-关系模式 2015-04-15

    C.关系模式(11种) 先来张图,看看这11中模式的关系: 第一类:通过父类与子类的关系进行实现. 第二类:两个类之间. 第三类:类的状态. 第四类:通过中间类 父类与子类关系 一.策略模式(strategy) 策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户.需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数,关系图如下: 图中ICalculator提供同意的方法,

  • 设计模式之模板模式 2015-04-20

    今天将模板模式应用到了新开发的插件中,顿时感觉高大上了,不仅缩减了代码重复率不说,而且对于程序的扩展性也有了很大的提高.真正在项目中体会到了使用设计模式的好处,所以将其归纳总结一下: 模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.这就是模板方法模式的用意. 模板方法模式的结构 模板方法模式是所有模式中最为常见的几个模式之一,是基于继

  • Java设计模式之策略模式(Strategy模式)介绍 2013-10-02

    这篇文章主要介绍了Java设计模式之策略模式(Strategy模式)介绍,Strategy是属于设计模式中对象行为型模式,要是定义一系列的算法,这些算法一个个封装成单独的类,需要的朋友可以参考下 Strategy是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类. Stratrgy应用比较广泛,比如,公司经营业务变化图,可能有两种实现方式,一个是线条曲线,一个是框图(bar),这是两种算法,可以使用Strategy实现. 这里以字符串替代为例,有一个文件,我

  • Java设计模式之创建者模式简介 2013-10-02

    这篇文章主要介绍了Java设计模式之创建者模式,需要的朋友可以参考下 Java的创建者模式与工厂模式有点类似,不过关注点不同.工厂模式往往只关心你要的是什么,而不关心这个东西的具体细节是什么.相对而言创建模式则是关心这个东西的具体细节的创建.拿创建人物来说,我们关心的不仅是创建一个人物,还要关心他的性别,肤色和名字,则可以使用创建者模式. 程序实例如下所示: package builder; /** * * DOC 种族角色 * */ public class Race { private St

  • 浅谈C#设计模式之代理模式 2013-11-07

    这篇文章主要介绍了浅谈C#设计模式之代理模式,需要的朋友可以参考下 代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口.根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理.远程代理.虚拟代理.缓冲代理等,它们应用于不同的场合,满足用户的不同需求 using System; using System.Collections.Generic; us

  • C++设计模式之原型模式 2013-11-18

    这篇文章主要介绍了C++设计模式之原型模式,本文讲解了什么是原型模式.为什么要使用原型模式.代码实例等内容,需要的朋友可以参考下 什么是原型模式? 在GOF的<设计模式:可复用面向对象软件的基础>中是这样说的:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.这这个定义中,最重要的一个词是"拷贝",也就是口头上的复制,而这个拷贝,也就是原型模式的精髓所在. 举一个最简单的例子来说明原型模式:记得上小学的时候,老师把需要做的课外习题写到黑板上,而下面的我们都要把

  • 深入理解JavaScript系列(35):设计模式之迭代器模式详解 2013-11-22

    这篇文章主要介绍了深入理解JavaScript系列(35):设计模式之迭代器模式详解,迭代器模式(Iterator):提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示,需要的朋友可以参考下 介绍 迭代器模式(Iterator):提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示. 迭代器的几个特点是: 1.访问一个聚合对象的内容而无需暴露它的内部表示. 2.为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作. 3.遍历的同时更改迭代

  • JavaScript设计模式之工厂模式和构造器模式 2013-11-23

    这篇文章主要介绍了JavaScript设计模式之工厂模式和构造器模式,本文同时讲解了设计模式的类别如创建型设计模式.结构型设计模式.行为设计模式等内容,需要的朋友可以参考下 什么是模式 前阵子准备期末考试,劳神又伤身的,实在闲不得空来更新文章,今天和大家说说javascript中的设计模式. 首先呢,我们需要知道的是:模式是一种可复用的解决方案,而反模式呢就是针对某个问题的不良解决方案. js反模式常见例子 1.向setTimeout和setInterval传递字符串,而不是函数,这会触发eva

  • Java设计模式之迭代模式(Iterator模式)介绍 2013-12-06

    这篇文章主要介绍了Java设计模式之迭代模式(Iterator模式)介绍,本文用一个老师点名的现象描述了迭代模式的使用,需要的朋友可以参考下 上了这么多年学,我发现一个问题,好象老师都很喜欢点名,甚至点名都成了某些老师的嗜好,一日不点名,就饭吃不香,觉睡不好似的,我就觉得很奇怪,你的课要是讲的好,同学又怎么会不来听课呢,殊不知:"误人子弟,乃是犯罪!"啊. 好了,那么我们现在来看老师这个点名过程是如何实现吧: 1.老规矩,我们先定义老师(Teacher)接口类: public inte

  • JAVA设计模式之解释器模式详解 2013-12-19

    这篇文章主要介绍了JAVA设计模式之解释器模式详解,解释器模式是类的行为模式,给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器,需要的朋友可以参考下 在阎宏博士的<JAVA与模式>一书中开头是这样描述解释器(Interpreter)模式的: 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 解释器模式的结构 下面就以一个示意性的系统为例,讨论解释器模式的结构.系统

  • JavaScript设计模式之外观模式介绍 2013-12-27

    这篇文章主要介绍了JavaScript设计模式之外观模式介绍,外观模式是用于由于子系统或程序组成较复杂而提供的一个高层界面接口,使用客户端更容易访问底层的程序或系统接口,需要的朋友可以参考下 外观模式说明 说明:外观模式是用于由于子系统或程序组成较复杂而提供的一个高层界面接口,使用客户端更容易访问底层的程序或系统接口; 外观模式是我们经常使用遇到的模式,我们经常涉及到的功能,可能需要涉及到几个子接口或子系统,而我们的某个功能,可能只需要这向个多个子接口中的一个或几个组成的顺序封装.如果是业务功能

  • JAVA设计模式之访问者模式详解 2013-12-28

    这篇文章主要介绍了JAVA设计模式之访问者模式详解,访问者模式是对象的行为模式,访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,需要的朋友可以参考下 在阎宏博士的<JAVA与模式>一书中开头是这样描述访问者(Visitor)模式的: 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变. 分派的概念 变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做

  • php重构优化一例--模板方法模式应用 2014-01-04

    最近优化php项目,记录下经验,直接上干活... php在公司项目中主要用于页面展现,前端有个view,view向后端的service请求数据,数据的传输格式是json.下面看优化前的service的代码: <?php require_once('../../../global.php'); require_once(INCLUDE_PATH.'/discache/CacherManager.php'); require_once(INCLUDE_PATH.'/oracle_oci.php');