设计模式(17) 访问者模式(VISITOR) C++实现

意图:

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

 

动机:

    之前在学校的最后一个小项目就是做一个编译器,当时使用的就是访问者模式。

    在静态分析阶段,将源程序表示为一个抽象语法树,编译器需要在抽象语法树的基础上实施某些操作以进行静态语义分析。可能需要定义许多操作以进行类型检查、代码优化、流程分析、检查变量是否在使用前被赋值,等等。

    这个需求的特点是:要求对不同的节点进行不同的处理。

    常规设计方法:不同的节点封装不同的操作。

    缺点是,节点类型过多,将操作分散在各个节点类中会导致整个系统难以理解、维护和修改。增加新的操作要修改和重新编译所有的类。

    改进:节点类独立于作用于其上的操作。

        1 将相关操作封装在一个独立的对象(Visitor)中,并在遍历抽象语法树时将此对象传递给当前访问的元素。

        2 当一个节点接受一个访问者时,该元素向访问者发送一个包含自身类信息的请求。该请求同时也将该元素本身作为一个参数。

        3 访问者将对该元素执行该操作。

 

适用性:

    在下列情况下使用Visitor模式:

    一个对象结构包含很多类对象

    需要对其中的对象进行很多不同的并且不相关的操作

    对象很少改变,经常需要对其上的操作进行修改或新增

    需要注意的一点是,如果对象结果和接口经常改变,那么会导致需要重定义所有访问者的接口,会导致很大的代价。所以这种情况还是在对象类中定义操作比较好。

 

结构:

clipboard

 

协作:

clipboard[1]

 

示例代码:

背景:假设你的电脑出现问题了 ,拿到售后那边检测,售后告诉你必须拆机检测,检测过程通过两个技术人员依次负责不同功能的检测。

分析:本例中,两个负责不同功能检测的技术人员就是Visitor,而电脑的各个部件就是elements。

特点:电脑的部件是固定的,不会有太大的改变,但是如果一种检测方式没有找出问题的话,那么就需要增加检测项。符合访问者模式的特点。

//visit.h#ifndef VISITOR_H
#define VISITOR_H#include <iostream>
#include <string>
#include <vector>class Element;
class CPU;
class VideoCard;
class MainBoard;/*------------------*/
class Visitor {
public:Visitor(std::string name) {visitorName = name;}virtual void visitCPU( CPU* cpu ) {};virtual void visitVideoCard( VideoCard* videoCard ) {};virtual void visitMainBoard( MainBoard* mainBoard ) {};std::string getName() {return this->visitorName;};
private:std::string visitorName;
};class Element {
public:Element( std::string name ) {eleName = name;}virtual void accept( Visitor* visitor ) {};virtual std::string getName() {return this->eleName;}
private:std::string eleName;
};/*----------- Elements -------------*/class CPU : public Element {
public:CPU(std::string name) : Element(name) {}void accept(Visitor* visitor) {visitor->visitCPU(this);}
};class VideoCard : public Element {
public:VideoCard(std::string name) : Element(name) {}void accept(Visitor* visitor) {visitor->visitVideoCard(this);}
};class MainBoard : public Element {
public:MainBoard(std::string name) : Element(name) {}void accept(Visitor* visitor) {visitor->visitMainBoard(this);}
};/*----------- ConcreteVisitor -------------*/class CircuitDetector : public Visitor {
public:CircuitDetector(std::string name) : Visitor(name) {}// checking cpuvoid visitCPU( CPU* cpu ) {std::cout << Visitor::getName() << " is checking CPU's circuits.(" << cpu->getName()<<")" << std::endl;}// checking videoCardvoid visitVideoCard( VideoCard* videoCard ) {std::cout << Visitor::getName() << " is checking VideoCard's circuits.(" << videoCard->getName()<<")" << std::endl;}// checking mainboardvoid visitMainBoard( MainBoard* mainboard ) {std::cout << Visitor::getName() << " is checking MainBoard's circuits.(" << mainboard->getName() <<")" << std::endl;}};class FunctionDetector : public Visitor {
public:FunctionDetector(std::string name) : Visitor(name) {}virtual void visitCPU( CPU* cpu ) {std::cout << Visitor::getName() << " is check CPU's function.(" << cpu->getName() << ")"<< std::endl;}// checking videoCardvoid visitVideoCard( VideoCard* videoCard ) {std::cout << Visitor::getName() << " is checking VideoCard's function.(" << videoCard->getName()<< ")" << std::endl;}// checking mainboardvoid visitMainBoard( MainBoard* mainboard ) {std::cout << Visitor::getName() << " is checking MainBoard's function.(" << mainboard->getName() << ")"<< std::endl;}
};/*------------------------*/class Computer {
public:Computer(CPU* cpu,VideoCard* videocard,MainBoard* mainboard) {elementList.push_back(cpu);elementList.push_back(videocard);elementList.push_back(mainboard);};void Accept(Visitor* visitor) {for( std::vector<Element*>::iterator i = elementList.begin(); i != elementList.end(); i++ ){(*i)->accept(visitor);}}; 
private:std::vector<Element*> elementList;
};#endif

 

 

// main.cpp#include "visitor.h"int main() {CPU* cpu = new CPU("Intel CPU");VideoCard* videocard = new VideoCard("XXX video card");MainBoard* mainboard = new MainBoard("HUAWEI mainboard");Computer* myComputer = new Computer(cpu, videocard, mainboard);CircuitDetector* Dan = new CircuitDetector("CircuitDetector Dan");FunctionDetector* Tom = new FunctionDetector("FunctionDetector Tom");std::cout << "\nStep 1: Dan is checking computer's circuits." << std::endl;myComputer->Accept(Dan);std::cout << "\nStep 2: Tom is checking computer's functions." << std::endl;myComputer->Accept(Tom);system("Pause");return 0;
}

 

 

运行截图:

clipboard[2]

 

 

 

参考资料:

《设计模式:可复用面向对象软件的基础》

转载于:https://www.cnblogs.com/suzhou/p/designpattern17visitor.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/575457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云服务器的主机名是否可以修改??

云服务器的主机名是否可以修改&#xff1f; 1 要是自己建的虚拟机等&#xff0c;这可以随便改&#xff0c;不影响。 2 要是云服务器&#xff0c;阿里云 华为云等&#xff0c;因为是项目上服务器厂商给提供的服务器信息&#xff0c;所以遇到问题需要改主机名时&#xff0c;为了…

CSS简介、行内样式、内部样式、外部样式、注释、引入其他CSS文件

CSS的发展历程&#xff1a; 起初是没有css的&#xff0c;只有少量样式是可以写在html标签中&#xff0c;这样代码格外显得臃肿&#xff0c;此时CSS就出现了。 初识CSS&#xff1a; CSS(Cascading Style Sheets),被称为CSS样式表或者层叠样式表&#xff0c;主要用于设置HTML页…

CISCO PVST+配置和结果验证 per vlan spanning tree(51cto 实验10)

1. 实验线路连接图使用Cisco Packet Tracer6.0 构建拓扑结构图 2. 实验内容(1) 参阅教材中内容&#xff0c;完成PVST的配置内容。(2) 在各台交换机上使用show spanning-tree vlan 10 和show spanning-tree vlan 20 命令&#xff0c;查看根桥信息、各端口角色和各端口状态。(3) …

Linux crond 每分钟,每小时,每天,每周,每月,每年 的表达式写法

每分钟执行 * * * * * 每五分钟执行 */5 * * * * 每小时执行(让分钟取0) 0 * * * * 每2小时执行 0 */2 * * * 每天执行 0 0 * * * 每周执行 0 0 * * 0 每月执行 0 0 1 * * 每年执行 0 0 1 1 *

css中选择器介绍

选择器&#xff1a; 选择器是用来选择目标元素的&#xff0c;选择器分基础选择器和复合选择器及伪类选择器。 基础选择器&#xff1a; 标签名{} /* 1 标签选择器&#xff1a;把某类标签全部选中&#xff0c;如下&#xff1a; */p{font-size:36px;}.类名{} /* 2 类选择器(clas…

使用iometer测试

对国产机进行测试 1.win7上安装测试 下载&#xff1a; 点击打开链接 双击安装即可。 2.ubuntu下配置&#xff1a; OS: Ubuntu 12.04LTS x86_64Kernel: 3.5.0-26-generic下载&#xff1a; 点击打开链接编译安装 unzip iometer-2006_07_27.common-src.zip\?download cd iometer…

http://mirrors.aliyuncs.com/centos/7/extras/x86_64/repodata/repomd.xml: [Errno 12] Timeout on http:/

对于这个点&#xff0c;我的情况是【errno12】&#xff0c; 众多帖子里还是请求404错误居多&#xff0c;情况不一样。我的安装阿里yum配置过程没问题&#xff0c;然后想起之前有过这样&#xff0c;怀疑是dns解析不到mirrors.aliyuncs.com这种地址&#xff0c;所以在dns文件里加…

Android网络课程笔记-----本地音乐播放

1. 本地音乐播放 多媒体&#xff1a; 图片&#xff1a;拍、图片查、图片编辑、摄像、图像处理算法 音频&#xff1a;录、回、编辑、MediaRecorde、MediaPlayer 视频&#xff1a;录、回、编辑、VideoView2. MediaPlayer的使用方法 MediaPlayer的声明周期转载…

CSS设置字体大小、字体粗细、字体风格

font-size:设置字体大小: 该属性值的单位可以使用相对单位和绝对单位&#xff0c;推荐使用px。(浏览器能够识别的最小像素是12px) p{font-size:20px;}常见尺寸单位&#xff1a; font-family:设置字体: 如果需要设置多个字体样式&#xff0c;则属性值可以写多个中间用逗号隔…

css设置字体颜色、文本对齐方式、首行缩进、文本装饰、列表样式、鼠标样式、禁止文本域拖拽、轮廓线、块级元素对齐方式、文字溢出设置

color:设置字体颜色: 取值方式有&#xff1a;1.颜色值red,green等 、2.十六进制#FF0000,#FF2313等、3.RGB代码rgb(225,225,112)或rgb(100%,55%,0%)&#xff0c;取值范围0-225&#xff0c;0%-100%&#xff0c;rgba是rgb的扩展&#xff0c;其中第四个参数设置的是透明度&#xf…

数字图像的5种增强处理

数字图像的5种增强处理#include<iostream>#include<cmath>using namespace std;int main(){ int i,j,n,m,w,a[100][100],x[100][100],max[100][100][20],b[100][100],k,p,u; cout<<"输入矩阵行列数:"; cin>>n>>m; cout<<"输…

json在线解析工具大集合

** json在线解析工具大集合 ** http://json.jsrun.net JSRUN推出的JSON视图工具&#xff0c;简洁易用&#xff0c;清晰明了。 可能是国内最好用的JSON工具了。 http://jsonview.net http://kjson.cn http://json.jsrun.pro http://json.jsrun.top http://json.jsrun.cn…

css中标签显示模式、块元素、行内元素、行内块元素、显示模式转换

标签显示模式display: HTML标签一般分为块标签&#xff08;块元素&#xff1a;block-level&#xff09;和行内标签&#xff08;行内元素&#xff1a;inline-level&#xff09;两种类型&#xff0c;但是还有第三种说法行内块元素&#xff1a;table-row-group&#xff1a;设置元…

MVC.Net: jqueryval错误

当使用Mvc.net创建Create表单后&#xff0c;firebug Create页面会出现404 Not Found - http://192.168.3.95:7001/bundles/jqueryval"的错误。检查Create.cshtml会发现在底部有这段代码&#xff1a; section Scripts { Scripts.Render("~/bundles/jqueryval") }…

mysql 介绍 怎么下载 驱动jar包 各种细节问题大详解

对碰到的问题做个记录总结。 1 MySQL 的官网下载地址&#xff1a;http://www.mysql.com/downloads/版本说明。 1. MySQL Community Server 社区版本&#xff0c;开源免费&#xff0c;但不提供官方技术支持。 2. MySQL Enterprise Edition 企业版本&#xff0c;需付费&#xff…

css书写规范、行高

css书写规范&#xff1a; 空格规范&#xff1a; 选择器与花括号{之间必须包含空格&#xff0c;属性冒号&#xff1a;后面和属性值必须包含空格 .text {font-size: 16px;}选择器规范&#xff1a; 当有多个选择器同时出现时&#xff0c;每个选择器必须独占一行 .box,.nav,.mai…

PHP在线支付

php网站如何做个页面接入网银在线支付接口&#xff1f; >有两个是用来接收网银在线的反馈传递页面(这两个页面一般是进行下面的第四步)一个是配置文件一个是网银在线的一些函数(一般不需要修改)1 先做商品支付页面2 用户确定提交订单(同时本地写入数据库一个唯一的订单号,并…

CSS中的层叠性、继承性、优先级、权重

css三大特性&#xff1a; 三大特性&#xff1a;层叠性、继承性、优先级 层叠性&#xff1a; 指多种css样式的叠加&#xff0c;是浏览器处理多种css样式冲突的能力&#xff0c;如果给一个元素通过不同或者相同的选择器设置相同的属性但属性值不同时&#xff0c;权重相同的情况…

struts2线程安全

struts2线程安全 2012-02-16 21:07:58分类&#xff1a; 系统运维 问题&#xff1a;Struts 2 Action对象为每一个请求产生一个实例&#xff0c;因此没有线程安全问题。Spring的Ioc容器管理的bean默认是单实例的,上一次请求处理的状态信息被保持下来&#xff0c;并影响了下一次的…