访问者模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。该模式的目的是要把处理从数据结构分离出来。访问者模式让增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。现在再来说说我之前经历过的那个项目。

是基于Windows Shell开发的一个项目,在一个容器中存储了很多的Shell Items,同时定义了对Items的操作,由于项目一直都在进行后期扩展,对Items的操作在后期都需要进行扩展的;而现在的做法是,定义一个操作类,该操作类中定义了一个集合,该集合存放Items,在该操作类中扩展对应的操作方法。现在想想如果使用访问者模式也是可以的,由于Items集合是固定的,当需要扩展集合的操作时,只需要添加对应的访问者即可。

UML类图

Visitor(访问者):为该对象结构中ConcreteElement的每一个类声明一个Visit操作。该操作的名字和特征标识了发送Visit请求给该访问者的那个类。这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
ConcreteVisitor(具体访问者):实现每个由Visitor声明的操作。每个操作实现本算法的一部分,而该算法片段乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。
Element(元素):定义一个Accept操作,它以一个访问者为参数。
ConcreteElement(具体元素):实现Accept操作,该操作以一个访问者为参数。
ObjectStructure(对象结构):能够枚举它的元素,同时提供一个高层的接口以允许该访问者访问它的元素。

使用场合

  1. 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作;
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中;
  3. 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作;
  4. 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

代码实现

#include <iostream>
#include <vector>
using namespace std;class ConcreteElementA;
class ConcreteElementB;class Visitor
{
public:virtual void VisitConcreteElementA(ConcreteElementA *pElementA) = 0;virtual void VisitConcreteElementB(ConcreteElementB *pElementB) = 0;
};class ConcreteVisitor1 : public Visitor
{
public:void VisitConcreteElementA(ConcreteElementA *pElementA);void VisitConcreteElementB(ConcreteElementB *pElementB);
};void ConcreteVisitor1::VisitConcreteElementA(ConcreteElementA *pElementA)
{// 现在根据传进来的pElementA,可以对ConcreteElementA中的element进行操作
}void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB *pElementB)
{// 现在根据传进来的pElementB,可以对ConcreteElementB中的element进行操作
}class ConcreteVisitor2 : public Visitor
{
public:void VisitConcreteElementA(ConcreteElementA *pElementA);void VisitConcreteElementB(ConcreteElementB *pElementB);
};void ConcreteVisitor2::VisitConcreteElementA(ConcreteElementA *pElementA)
{// ...
}void ConcreteVisitor2::VisitConcreteElementB(ConcreteElementB *pElementB)
{// ...
}// Element object
class Element
{
public:virtual void Accept(Visitor *pVisitor) = 0;
};class ConcreteElementA : public Element
{
public:void Accept(Visitor *pVisitor);
};void ConcreteElementA::Accept(Visitor *pVisitor)
{pVisitor->VisitConcreteElementA(this);
}class ConcreteElementB : public Element
{
public:void Accept(Visitor *pVisitor);
};void ConcreteElementB::Accept(Visitor *pVisitor)
{pVisitor->VisitConcreteElementB(this);
}// ObjectStructure类,能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素
class ObjectStructure
{
public:void Attach(Element *pElement);void Detach(Element *pElement);void Accept(Visitor *pVisitor);private:vector<Element *> elements;
};void ObjectStructure::Attach(Element *pElement)
{elements.push_back(pElement);
}void ObjectStructure::Detach(Element *pElement)
{vector<Element *>::iterator it = find(elements.begin(), elements.end(), pElement);if (it != elements.end()){elements.erase(it);}
}void ObjectStructure::Accept(Visitor *pVisitor)
{// 为每一个element设置visitor,进行对应的操作for (vector<Element *>::const_iterator it = elements.begin(); it != elements.end(); ++it){(*it)->Accept(pVisitor);}
}int main()
{ObjectStructure *pObject = new ObjectStructure;ConcreteElementA *pElementA = new ConcreteElementA;ConcreteElementB *pElementB = new ConcreteElementB;pObject->Attach(pElementA);pObject->Attach(pElementB);ConcreteVisitor1 *pVisitor1 = new ConcreteVisitor1;ConcreteVisitor2 *pVisitor2 = new ConcreteVisitor2;pObject->Accept(pVisitor1);pObject->Accept(pVisitor2);if (pVisitor2) delete pVisitor2;if (pVisitor1) delete pVisitor1;if (pElementB) delete pElementB;if (pElementA) delete pElementA;if (pObject) delete pObject;return 0;
}

总结

访问者模式的基本思想如下:首先拥有一个由许多对象构成的对象结构,就是上面代码中的ObjectStructure,这些对象的类都拥有一个Accept方法用来接受访问者对象;访问者是一个接口,它拥有一个Visit方法,这个方法对访问到的对象结构中不同类型的元素做出不同的操作;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施Accept方法,在每一个元素的Accept方法中回调访问者的Visit方法,从而使访问者得以处理对象结构的每一个元素。我们就可以针对对象结构设计不同的访问者类来完成不同的操作。

设计模式中经常说的一句话是:发现变化并封装之。是否采用访问者模式,就要看“变化”是什么。访问者模式中,“变化”是具体访问者,其次是对象结构;但是,如果具体元素也会发生改变,就万万不能使用访问者模式,因为这样“牵一发而动全身”,后期的维护性就太差了。

C++设计模式——访问者模式相关推荐

  1. 设计模式 访问者模式

    文章目录 访问者模式 访问者模式实战 访问者模式 在相同的数据结构下, 增加容易变化的业务访问逻辑, 为了增强扩展性, 将易变的访问逻辑进行解耦的一种设计模式. 访问者模式实战 模拟学校中, 有老师和 ...

  2. 设计模式---访问者模式

    访问者模式 介绍 定义及使用场景 UML类图 角色 财务案例 个人心得体会 静态分派以及动态分派 静态分派 动态分派 访问者模式中的伪动态双分派 对访问者模式的一些思考 总结 优点 缺点 适用性 参考 ...

  3. C++设计模式——访问者模式(visitor pattern)

    一.原理讲解 1.1意图 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 1.2应用场景 一个对象结构包含很多类对象,它们有不同的接口,而你 ...

  4. java设计模式---访问者模式

      Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自 己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广 泛,遵循一定的编程模式,才能使自 ...

  5. yii2通过url访问类中的方法_行为型设计模式 访问者模式

    author zong email zongzhe1996@163.com 介绍 在访问者模式中,通过使用一个访问者类,可以改变元素类(被访问者)的执行算法.元素类的执行算法可以随着访问者的改变而改变 ...

  6. C++设计模式-访问者模式

    目录 基本概念 代码与实例 基本概念 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变元素的类的前提下定义作用于这些元素的新操作. UML图如下(此图来源于大 ...

  7. PHP设计模式——访问者模式

    声明:本系列博客参考资料<大话设计模式>,作者程杰. 访问者模式表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. UML类图: 角色 ...

  8. C#设计模式——访问者模式(Vistor Pattern)

    一.引言 在上一篇博文中分享了责任链模式,责任链模式主要应用在系统中的某些功能需要多个对象参与才能完成的场景.在这篇博文中,我将为大家分享我对访问者模式的理解. 二.访问者模式介绍 2.1 访问者模式 ...

  9. 大话设计模式—访问者模式

    在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法.通过这种方式,元素的执行算法可以随着访问者改变而改变.这种类型的设计模式属于行为型模式.根据模式,元 ...

最新文章

  1. c语言 amp 位与 什么意思,C语言中amp;是什么意思?--龙方网络
  2. 初识遗传算法 蚁群算法
  3. 资料收集新一代 Linux 文件系统 btrfs 简介
  4. JSF Struts Spring Hibernate 整合
  5. java 多态性 变量_java – 与实例变量的多态性
  6. 手机压缩包删除有什么后果?
  7. android的多行文本框的值,Swift - 多行文本输入框(UITextView)
  8. 实用网站 |懒人爱学习
  9. JAVA里面==和euqals的区别
  10. LongAdder原理
  11. Tera Term使用说明
  12. ffmpeg显卡快速压制单/双语字幕视频
  13. 一文读懂hosts文件
  14. 树莓派接3.5mm音响没有声音及音量调节
  15. Windows定时关机小程序
  16. 360开机小助手的广告怎么关
  17. 淘宝钓鱼网站抓不住吗
  18. .globl _start
  19. 在公路项目里路缘石滑模机施工作业需要注意这些
  20. 纯javascript实现赛车小游戏

热门文章

  1. excel显著性检验_#如何用excel做anova分析#用excel做显著性分析
  2. 【win10系统重装】
  3. 京东面试详解(渣渣吐血整理版)
  4. 《塞尔达传说》与氛围游戏的兴起:在游戏中感受禅意
  5. JAVA代码托管平台_推荐几个常用的代码托管平台
  6. XML/JSON 语法随堂笔记
  7. java使用ffmpeg将视频转码
  8. 判断天干,地支,生肖推算
  9. python 批量转换xls to xlsx,出现pywintypes.com_error: (-2147417848, ‘被调用的对象已与其客户端断开连接)’的问题处理
  10. 信息安全之加密域可逆信息隐藏