软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书,对于每个模式,用C++写了个小例子,加深一下理解。主要参考《大话设计模式》和《设计模式:可复用面向对象软件的基础》两本书。本文介绍策略模式的实现。

策略模式是指定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。也就是说这些算法所完成的功能一样,对外的接口一样,只是各自实现上存在差异。用策略模式来封装算法,效果比较好。下面以高速缓存(Cache)的替换算法为例,实现策略模式。

什么是Cache的替换算法呢?简单解释一下, 当发生Cache缺失时,Cache控制器必须选择Cache中的一行,并用欲获得的数据来替换它。所采用的选择策略就是Cache的替换算法。下面给出相应的UML图。

ReplaceAlgorithm是一个抽象类,定义了算法的接口,有三个类继承自这个抽象类,也就是具体的算法实现。Cache类中需要使用替换算法,因此维护了一个  ReplaceAlgorithm的对象。这个UML图的结构就是策略模式的典型结构。下面根据UML图,给出相应的实现。

首先给出替换算法的定义。

[cpp] view plaincopy print?
  1. //抽象接口
  2. class ReplaceAlgorithm
  3. {
  4. public:
  5. virtual void Replace() = 0;
  6. };
  7. //三种具体的替换算法
  8. class LRU_ReplaceAlgorithm : public ReplaceAlgorithm
  9. {
  10. public:
  11. void Replace() { cout<<"Least Recently Used replace algorithm"<<endl; }
  12. };
  13. class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm
  14. {
  15. public:
  16. void Replace() { cout<<"First in First out replace algorithm"<<endl; }
  17. };
  18. class Random_ReplaceAlgorithm: public ReplaceAlgorithm
  19. {
  20. public:
  21. void Replace() { cout<<"Random replace algorithm"<<endl; }
  22. };

接着给出Cache的定义,这里很关键,Cache的实现方式直接影响了客户的使用方式,其关键在于如何指定替换算法。

方式一:直接通过参数指定,传入一个特定算法的指针。

[cpp] view plaincopy print?
  1. //Cache需要用到替换算法
  2. class Cache
  3. {
  4. private:
  5. ReplaceAlgorithm *m_ra;
  6. public:
  7. Cache(ReplaceAlgorithm *ra) { m_ra = ra; }
  8. ~Cache() { delete m_ra; }
  9. void Replace() { m_ra->Replace(); }
  10. };

如果用这种方式,客户就需要知道这些算法的具体定义。只能以下面这种方式使用,可以看到暴露了太多的细节。

[cpp] view plaincopy print?
  1. int main()
  2. {
  3. Cache cache(new LRU_ReplaceAlgorithm()); //暴露了算法的定义
  4. cache.Replace();
  5. return 0;
  6. }

方式二:也是直接通过参数指定,只不过不是传入指针,而是一个标签。这样客户只要知道算法的相应标签即可,而不需要知道算法的具体定义。

[cpp] view plaincopy print?
  1. //Cache需要用到替换算法
  2. enum RA {LRU, FIFO, RANDOM}; //标签
  3. class Cache
  4. {
  5. private:
  6. ReplaceAlgorithm *m_ra;
  7. public:
  8. Cache(enum RA ra)
  9. {
  10. if(ra == LRU)
  11. m_ra = new LRU_ReplaceAlgorithm();
  12. else if(ra == FIFO)
  13. m_ra = new FIFO_ReplaceAlgorithm();
  14. else if(ra == RANDOM)
  15. m_ra = new Random_ReplaceAlgorithm();
  16. else
  17. m_ra = NULL;
  18. }
  19. ~Cache() { delete m_ra; }
  20. void Replace() { m_ra->Replace(); }
  21. };

相比方式一,这种方式用起来方便多了。其实这种方式将简单工厂模式与策略模式结合在一起,算法的定义使用了策略模式,而Cache的定义其实使用了简单工厂模式。

[cpp] view plaincopy print?
  1. int main()
  2. {
  3. Cache cache(LRU); //指定标签即可
  4. cache.Replace();
  5. return 0;
  6. }

上面两种方式,构造函数都需要形参。构造函数是否可以不用参数呢?下面给出第三种实现方式。

方式三:利用模板实现。算法通过模板的实参指定。当然了,还是使用了参数,只不过不是构造函数的参数。在策略模式中,参数的传递难以避免,客户必须指定某种算法。

[cpp] view plaincopy print?
  1. //Cache需要用到替换算法
  2. template <class RA>
  3. class Cache
  4. {
  5. private:
  6. RA m_ra;
  7. public:
  8. Cache() { }
  9. ~Cache() { }
  10. void Replace() { m_ra.Replace(); }
  11. };

使用方式如下:

[cpp] view plaincopy print?
  1. int main()
  2. {
  3. Cache<Random_ReplaceAlgorithm> cache; //模板实参
  4. cache.Replace();
  5. return 0;
  6. }

设计模式C++实现(2)——策略模式相关推荐

  1. 设计模式初学者系列-策略模式 -------为什么总是继承

    设计模式初学者系列-策略模式                                                 -------为什么总是继承 模板方法的延续 这篇稿子是基于我的前一篇模板 ...

  2. 老王讲设计模式(一)——策略模式

    策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 老王最近接到一个工作,上 ...

  3. 设计模式(三)策略模式——在Spring中使用策略模式

    前言 在 设计模式(一)策略模式 -- 策略模式结构 和 设计模式(二)策略模式 -- 在程序中通过枚举使用策略模式 两篇博文中分析了策略模式的基础使用,在实际的项目开发中要结合spring容器使用策 ...

  4. 设计模式 by Python1:策略模式

    设计模式 by Python1:策略模式 最近开始重新看<Head First 设计模式>,作为一个不错的练习,打算在整理设计模式笔记的时候用Python实现. 作为第一个介绍的设计模式, ...

  5. C++设计模式学习笔记:策略模式

    C++设计模式学习笔记:策略模式 策略模式设计商场促销 1.策略模式介绍 2.商场收银系统策略模式实现 3.策略模式与工厂模式结合 3.策略模式与工厂模式对比 策略模式设计商场促销 1.策略模式介绍 ...

  6. 设计模式解读之一: 策略模式——鸭子游戏

    设计模式解读之一: 策略模式--鸭子游戏 当我们掌握了Java的语法,当我们了解了面向对象的封装.继承.多态等特性,当我们可以用Swing.Servlet.JSP技术构建桌面以及Web应用,不意味着我 ...

  7. lt;二gt;读lt;lt;大话设计模式gt;gt;之策略模式

    又和大家见面了.可以坚持写出第二篇文章真不错,好好加油. <<大话设计模式>>解说策略模式是以商场收银软件程序开头的,那么问题来了.哪家商场收银软件强,开玩笑了. 读过上篇文章 ...

  8. 【HeadFirst 设计模式总结】1.策略模式

    1.书中举了一个鸭子类的设计,有些会飞或者会叫,有些不会飞可能也不会叫,用继承则导致不该有的功能通过继承而继承了下来,使用接口则代码无法做到最大程度的重用.进而引出设计原则1:找出应用中可能需要变化之 ...

  9. 设计模式学习笔记--Strategy 策略模式

    所谓策略模式(Strategy Pattern),就是将策略 (算法) 封装为一个对象,易于相互替换,如同 USB 设备一样可即插即用:如果将策略.具体的算法和行为,编码在某个类或客户程序内部,将导至 ...

  10. 大话设计模式(八 用“策略模式”是一种好策略)

    (续上篇) 小菜次日来找大鸟,说:"<深入浅出设计模式>的第一章我看完了,它讲的是策略模式(Strategy).『策略模式』定义了算法家族,分别封装起来,让它们之间可以互相替换, ...

最新文章

  1. tkinter学习系列之(五)Checkbutton控件
  2. mysql导出数据字典6_MySQL利用Navicat导出数据字典
  3. 如何通过组件化提高开发效率?
  4. C#中的表达式和运算符
  5. 现代计算机教室布置图片,高中教室布置设计图
  6. android ROM ---(1)高通平台 Android O 升级学习
  7. 电脑能开机但进不去系统,电脑只能进安全模式怎么处理?
  8. MSP借助五招让中小企业签约云计算服务
  9. c++排序算法之 快速排序
  10. rman备份优化思路
  11. 随机森林模型及案例(Python)
  12. 用python编程小程序制作_一个非常适合Python新手的编程案例——投票小程序
  13. 十二个常见的Web安全漏洞总结及防范措施
  14. Windows 10 创意者更新-1703所有版本汇总
  15. sub 对应php什么函数,subtotal函数的使用方法1-9分别什么意思
  16. bootStrap常用样式
  17. 纵观DeSci:起源、代表项目与未来发展
  18. 响应式微服务_低风险整体式微服务演进第三部分
  19. js诟病Typescript、Java、JavaScript之间的借鉴与总结
  20. linux下卸载软件命令行,如何使用Linux中的命令行卸载软件 | MOS86

热门文章

  1. LSTM:《Long Short-Term Memory》的翻译并解读
  2. 使用容器与云计算技术快速进行深度学习
  3. TensorFlowIO操作(一)----线程和队列
  4. 决策树python建模中的坑 :ValueError: Expected 2D array, got 1D array instead:
  5. jquery通过ajax提交form
  6. 60行代码俄罗斯方块
  7. Oracle10g的flashback drop
  8. viso图片转eps文件 AND pdf转eps文件
  9. STM32F103 SPI flash操作注意事项
  10. 波卡链Substrate (7)Babe协议六“Secondary slot leader”