一. 访问者模式

定义:表示一个作用于某对象结构中的各元素的操作。它你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

结构如下:

二. 举例

假设有一项科学实验,是用来对比两种种子在不同环境下的生长情况。

两种种子,一种是普通的种子(Seed_A),一种是太空运回的种子(Seed_B)。

生长环境,分别是在多雨环境下(Rain_Status),阳光环境下(Sun_Status)等等。

结构如下:

代码如下:

  1. //状态
  2. class Status
  3. {
  4. public:
  5. virtual ~Status() {}
  6. virtual void VisitSeed_A(Seed* elm) {}
  7. virtual void VisitSeed_B(Seed* elm) {}
  8. protected:
  9. Status() {}
  10. };
  11. //下雨状态
  12. class Rain_Status:public Status
  13. {
  14. public:
  15. Rain_Status() {}
  16. virtual ~Rain_Status() {}
  17. //下雨状态下A种子生长的情况
  18. virtual void VisitSeed_A(Seed* elm)
  19. {
  20. cout<<"Rain will visit Seed A..."<<endl;
  21. }
  22. //下雨状态下B种子生长的情况
  23. virtual void VisitSeed_B(Seed* elm)
  24. {
  25. cout<<"Rain will visit Seed B..."<<endl;
  26. }
  27. };
  28. //阳光状态
  29. class Sun_Status:public Status
  30. {
  31. public:
  32. Sun_Status() {}
  33. virtual ~Sun_Status() {}
  34. //阳光状态下A种子生长的情况
  35. virtual void VisitSeed_A(Seed* elm)
  36. {
  37. cout<<"Sun will visit Seed A..."<<endl;
  38. }
  39. //阳光状态下B种子生长的情况
  40. virtual void VisitSeed_B(Seed* elm)
  41. {
  42. cout<<"Sun will visit Seed B..."<<endl;
  43. }
  44. };
  45. //种子
  46. class Seed
  47. {
  48. public:
  49. virtual ~Seed() {}
  50. virtual void Accept(Status* vis) = 0;
  51. protected:
  52. Seed() {}
  53. };
  54. //种子A,假设为普通种子
  55. class Seed_A:public Seed
  56. {
  57. public:
  58. Seed_A() {}
  59. ~Seed_A() {}
  60. void Accept(Status* vis)
  61. {
  62. vis->VisitSeed_A(this);
  63. }
  64. };
  65. //种子B,假设为从太空带回来的种子
  66. class Seed_B:public Seed
  67. {
  68. public:
  69. Seed_B() {}
  70. ~Seed_B() {}
  71. void Accept(Status* vis)
  72. {
  73. vis->VisitSeed_B(this);
  74. }
  75. };
  76. //对象结构类,为了对比不同种子
  77. class ObjectStructure
  78. {
  79. private:
  80. list<Seed*> lseed;
  81. public:
  82. //Add
  83. void Attach(Seed* seed)
  84. {
  85. lseed.push_back(seed);
  86. }
  87. //Delete
  88. void Detach(Seed* seed)
  89. {
  90. lseed.remove(seed);
  91. }
  92. //Show
  93. void Display(Status* status)
  94. {
  95. list<Seed*>::iterator it = lseed.begin();
  96. for (it; it != lseed.end(); ++it)
  97. {
  98. (*it)->Accept(status);
  99. }
  100. }
  101. };
  102. //测试代码
  103. int main(int argc,char* argv[])
  104. {
  105. ObjectStructure obj;
  106. //加入要对比的两个种子
  107. obj.Attach(new Seed_A());
  108. obj.Attach(new Seed_B());
  109. //查看各种状态下两个种子的情况
  110. obj.Display(new Rain_Status());
  111. //Sun Satte
  112. obj.Display(new Sun_Status());
  113. return 0;
  114. }

三. 说明

1. 首先有一点要明确,就是两种种子不会轻易改变,也就是只有普通和太空种子两种。换句话说就是,数据结构比较稳定。

2. 可以变的是新增的状态,比如增加一个X光下的生成情况,等等。说白了就是,操作集合可以相对自由的演化。

3. 这种结构的优点是,增加新的操作很容易;缺点是,增加新的数据结构有点困难,因为你要在每一个访问者里都添加相应的操作。

4. 种子生长图相对于访问者模式的结构图有如下关系:

seed(种子)相当于 element(元素),这个是不怎么变的。

status(状态) 相当于 visitor(访问者),这个是可变且易变的。要注意的是,每个访问者都要对所有的元素(element)进行操作。

5. 事实上我们很少用这种模式,因为数据结构(element)不变的情况很少。

设计模式C++描述----22.访问者(Visitor)模式的更多相关文章

  1. 设计模式之第22章-组合模式(Java实现)

    设计模式之第22章-组合模式(Java实现) “鱼哥,有没有什么模式是用来处理树形的“部分与整体”的层次结构的啊.”“当然”“没有?”“有啊.别急,一会人就到了.” 组合模式之自我介绍 “请问你是?怎 ...

  2. 《图解设计模式》读书笔记6-1 VISITOR模式

    目录 1. Visitor模式简介 2. 示例 2.1 类图 2.2 代码 3. 模式的角色和类图 4. 思路拓展 4.1 双重分发 4.2 开闭原则 4.3 难以增加ConcreteElement角 ...

  3. 设计模式-访问者(Visitor)模式

    访问者模式是对象的行为模式.访问者模式的目的是封装施加在某种数据结构元素上的操作.一旦一些操作需要修改,接受这个操作的数据结构可以保持不变. 个人觉得访问者模式相对其他的设计模式来说稍微复杂,难理解一 ...

  4. [设计模式]访问者 Visitor 模式

    访问者模式是对象的行为模式. 访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变.

  5. C++设计模式实现--訪问者(Visitor)模式

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/L_Andy/article/details/36896645 一. 訪问者模式 定义:表示一个作用于 ...

  6. 设计模式C++描述----09.桥接(Bridge)模式

    一. 举例 N年前: 计算机最先出来时,软件和硬件是一绑在一起的,比如IBM出了一台电脑,上面有一个定制的系统,假如叫 IBM_Win,这个IBM_Win系统当然不能在HP电脑上运行,同样HP出的HP ...

  7. 设计模式C++描述----21.解释器(Iterpreter)模式

    一. 解释器模式 定义:给定一个语言,定义它的文法的一种表示,并定一个解释器,这个解释器使用该表示来解释语言中的句子. 结构如下: 代码如下: //包含解释器之外的一些全局信息 class Conte ...

  8. 设计模式C++描述----20.迭代器(Iterator)模式

    一. 举例说明 我们知道,在 STL 里提供 Iterator 来遍历 Vector 或者 List 数据结构. Iterator 模式也正是用来解决对一个聚合对象的遍历问题,将对聚合的遍历封装到一个 ...

  9. 设计模式C++描述----19.命令(Command)模式

    一. 举例说明 我们知道,在多线程程序中,多个用户都给系统发 Read 和 Write 命令.这里有几点需要说明: 1. 首先明确一点,所有的这些 Read 和 Write 命令都是调用一个库函数. ...

随机推荐

  1. 基于Docker搭建大数据集群(四)Spark部署

    主要内容 spark部署 前提 zookeeper正常使用 JAVA_HOME环境变量 HADOOP_HOME环境变量 安装包 微云下载 | tar包目录下 Spark2.4.4 一.环境准备 上传到 ...

  2. Google资深工程师深度讲解Go语言★

    课程目录 第1章 课程介绍 第2章 基础语法 第3章 内建容器 第4章 面向“对象” 第5章 面向接口 第6章 函数式编程 第7章 错误处理和资源管理 第8章 测试与性能调优 第9章 Goroutin ...

  3. CSS技巧(1)· CSS渐变 linear-gradient

    前言: 不论在网页设计中,还是传统的媒介中,各种尺寸,颜色,角度的图案在视觉中无处不在,要想在网页中实现复杂的图案,其过程往往不够理想,过去,我们可以创建一个单独的位图文件,然后每次需要做调整的时候, ...

  4. navicat工具 pymysql模块

    目录 一 IDE工具介绍(Navicat) 二 pymysql模块 一 IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具,我们使用Navi ...

  5. 访问http接口时返回502 Bad Getway什么原因怎么解决

    使用 httpclient 工具通过代理服务器请求第三方http 接口,多次返回 502 Bad Getway,少数返回正常. 502 Bad Getway是什么意思? 502 Bad Gateway ...

  6. vue项目引入bootstrap正确姿势

    vue如何引入bootstrap 最近在玩全栈,自然少不了vue的使用.使用vue-cli生成的项目想引入bootstrap,需要先安装相应的npm包,然后在代码中显示引入. 1.安装依赖包: cnp ...

  7. KafkaStream简介

    Kafka Streams 1 概述 Kafka Streams是一个客户端程序库,用于处理和分析存储在Kafka中的数据,并将得到的数据写回Kafka或发送到外部系统.Kafka Stream基于一 ...

  8. Python中的可变对象与不可变对象、浅拷贝与深拷贝

    Python中的对象分为可变与不可变,有必要了解一下,这会影响到python对象的赋值与拷贝.而拷贝也有深浅之别. 不可变对象 简单说就是某个对象存放在内存中,这块内存中的值是不能改变的,变量指向这块 ...

  9. Fiddler的安装

    相关下载软件(链接:https://pan.baidu.com/s/1HFdFNph6FGHOFtZq09ldpg 提取码:3u3l ) fiddler是基于.net环境的,所以需要先安装.net 安 ...

  10. mysql 延时注入新思路

    转自先知社区https://xz.aliyun.com/t/2288 在4月的pwnhub比赛中,我们遇到了一个比较神奇的问题,如果在注入中遇到需要延时注入的情况,但服务端过滤了我们一般使用的slee ...