访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。例如处方单中的各种药品信息就是被访问的元素,而划价人员和药房工作人员就是访问者。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。

在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为“对象结构”,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。

访问者模式定义如下:

访问者模式(Visitor Pattern):提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。

访问者模式的结构较为复杂,其结构如图26-2所示:

在访问者模式结构图中包含如下几个角色:

●Vistor(抽象访问者):抽象访问者为对象结构中每一个具体元素类ConcreteElement声明一个访问操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型,具体访问者需要实现这些操作方法,定义对这些元素的访问操作。

●ConcreteVisitor(具体访问者):具体访问者实现了每个由抽象访问者声明的操作,每一个操作用于访问对象结构中一种类型的元素。

●Element(抽象元素):抽象元素一般是抽象类或者接口,它定义一个accept()方法,该方法通常以一个抽象访问者作为参数。【稍后将介绍为什么要这样设计。】

●ConcreteElement(具体元素):具体元素实现了accept()方法,在accept()方法中调用访问者的访问方法以便完成对一个元素的操作。

● ObjectStructure(对象结构):对象结构是一个元素的集合,它用于存放元素对象,并且提供了遍历其内部元素的方法。它可以结合组合模式来实现,也可以是一个简单的集合对象,如一个List对象或一个Set对象。

访问者模式中对象结构存储了不同类型的元素对象,以供不同访问者访问。访问者模式包括两个层次结构,一个是访问者层次结构,提供了抽象访问者和具体访问者,一个是元素层次结构,提供了抽象元素和具体元素。相同的访问者可以以不同的方式访问不同的元素,相同的元素可以接受不同访问者以不同访问方式访问。在访问者模式中,增加新的访问者无须修改原有系统,系统具有较好的可扩展性。

在访问者模式中,抽象访问者定义了访问元素对象的方法,通常为每一种类型的元素对象都提供一个访问方法,而具体访问者可以实现这些访问方法。这些访问方法的命名一般有两种方式:一种是直接在方法名中标明待访问元素对象的具体类型,如visitElementA(ElementA elementA),还有一种是统一取名为visit(),通过参数类型的不同来定义一系列重载的visit()方法。当然,如果所有的访问者对某一类型的元素的访问操作都相同,则可以将操作代码移到抽象访问者类中,其典型代码如下所示:

[java] view plain copy
  1. abstract class Visitor
  2. {
  3. public abstract void visit(ConcreteElementA elementA);
  4. public abstract void visit(ConcreteElementB elementB);
  5. public void visit(ConcreteElementC elementC)
  6. {
  7. //元素ConcreteElementC操作代码
  8. }
  9. }

在这里使用了重载visit()方法的方式来定义多个方法用于操作不同类型的元素对象。在抽象访问者Visitor类的子类ConcreteVisitor中实现了抽象的访问方法,用于定义对不同类型元素对象的操作,具体访问者类典型代码如下所示:

[java] view plain copy
  1. class ConcreteVisitor extends Visitor
  2. {
  3. public void visit(ConcreteElementA elementA)
  4. {
  5. //元素ConcreteElementA操作代码
  6. }
  7. public void visit(ConcreteElementB elementB)
  8. {
  9. //元素ConcreteElementB操作代码
  10. }
  11. }

对于元素类而言,在其中一般都定义了一个accept()方法,用于接受访问者的访问,典型的抽象元素类代码如下所示:

[java] view plain copy
  1. interface Element
  2. {
  3. public void accept(Visitor visitor);
  4. }

需要注意的是该方法传入了一个抽象访问者Visitor类型的参数,即针对抽象访问者进行编程,而不是具体访问者,在程序运行时再确定具体访问者的类型,并调用具体访问者对象的visit()方法实现对元素对象的操作。在抽象元素类Element的子类中实现了accept()方法,用于接受访问者的访问,在具体元素类中还可以定义不同类型的元素所特有的业务方法,其典型代码如下所示:

[java] view plain copy
  1. class ConcreteElementA implements Element
  2. {
  3. public void accept(Visitor visitor)
  4. {
  5. visitor.visit(this);
  6. }
  7. public void operationA()
  8. {
  9. //业务方法
  10. }
  11. }

在具体元素类ConcreteElementA的accept()方法中,通过调用Visitor类的visit()方法实现对元素的访问,并以当前对象作为visit()方法的参数。其具体执行过程如下:

(1) 调用具体元素类的accept(Visitor visitor)方法,并将Visitor子类对象作为其参数

(2) 在具体元素类accept(Visitor visitor)方法内部调用传入的Visitor对象的visit()方法,如visit(ConcreteElementA elementA),将当前具体元素类对象(this)作为参数,如visitor.visit(this);

(3) 执行Visitor对象的visit()方法,在其中还可以调用具体元素对象的业务方法。

这种调用机制也称为“双重分派”,正因为使用了双重分派机制,使得增加新的访问者无须修改现有类库代码,只需将新的访问者对象作为参数传入具体元素对象的accept()方法,程序运行时将回调在新增Visitor类中定义的visit()方法,从而增加新的元素访问方式。

 

思考

双重分派机制如何用代码实现?

在访问者模式中,对象结构是一个集合,它用于存储元素对象并接受访问者的访问,其典型代码如下所示:

[java] view plain copy
  1. class ObjectStructure
  2. {
  3. private ArrayList<Element> list = new ArrayList<Element>(); //定义一个集合用于存储元素对象
  4. public void accept(Visitor visitor)
  5. {
  6. Iterator i=list.iterator();
  7. while(i.hasNext())
  8. {
  9. ((Element)i.next()).accept(visitor); //遍历访问集合中的每一个元素
  10. }
  11. }
  12. public void addElement(Element element)
  13. {
  14. list.add(element);
  15. }
  16. public void removeElement(Element element)
  17. {
  18. list.remove(element);
  19. }
  20. }

在对象结构中可以使用迭代器对存储在集合中的元素对象进行遍历,并逐个调用每一个对象的accept()方法,实现对元素对象的访问操作。

 

思考

访问者模式是否符合“开闭原则”?【从增加新的访问者和增加新的元素两方面考虑。】

转载于:https://www.cnblogs.com/snowbook/p/5207835.html

设计模式--23、访问者模式相关推荐

  1. [设计模式] 23 访问者模式 visitor Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作.访问 ...

  2. C++设计模式23——访问者模式

    https://blog.csdn.net/CoderAldrich/article/details/83270301 访问者模式 在GOF的<设计模式:可复用面向对象软件的基础>一书中对 ...

  3. Java设计模式(访问者模式-迭代器模式-观察者模式-中介者模式)

    Java设计模式Ⅶ 1.访问者模式 1.1 访问者模式概述 1.2 代码理解 2.迭代器模式 2.1 迭代器模式概述 2.2 代码理解 3.观察者模式 3.1 观察者模式概述 3.2 代码理解 4.中 ...

  4. 北风设计模式课程---访问者模式(Visitor)

    北风设计模式课程---访问者模式(Visitor) 一.总结 一句话总结: 设计模式是日常问题的经验总结方案,所以学好设计模式对日常出现的问题可以有很好的解决. 访问者设计模式有点神似 抽象工厂模式, ...

  5. java的string访问某个元素_C#深究.net常用的23种设计模式之访问者模式(Vistor Pattern)...

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

  6. 在王者荣耀角度下分析面向对象程序设计B中23种设计模式之访问者模式

    · 访问者模式在王者荣耀中的应用 · 一.简述 在王者荣耀的社交系统中有2大核心,一为好友系统二为战队系统,好友系统偏向于个人,战队系统偏向于一个集体.玩家可以自己筹备创建战队.亦可加入其他战队.战队 ...

  7. 23种设计模式之访问者模式

    访问者模式的定义 定义: 封装一些作用于某种数据结构中的各元素的操作, 它可以在不改变数据结构的前提下定义作用于这些元素的新的操作 通俗的说, 就是定义一个访问者角色, 当对指定角色进行访问时要通过访 ...

  8. 深入理解23种设计模式(14) -- 访问者模式

    介绍 访问者模式 (Visitor Pattern) : 封装一些作用于某种数据结构的各元素操作,它可以在不改变数据结构的前提下定义作用于这些元素新的操作. 主要将数据结构与数据操作分离,解决数据结构 ...

  9. 设计模式之访问者模式(Visitor)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  10. Android设计模式之——访问者模式

    一.介绍 访问者模式是一种将数据操作与数据结构分离的设计模式,它是<设计模式>中23种设计模式中最复杂的一个,但它的使用频率并不高,正如<设计模式>的作者GOF对访问者模式的描 ...

最新文章

  1. Linux系统JDK安装和配置
  2. 参加完Python培训后有哪些就业方向
  3. python查题_python 数据库连表查询习题
  4. java list主要实现_java容器-list的常用实现及原理
  5. c++ 数组指针形参,并返回数据
  6. Python使用LDAP做用户认证
  7. 利用MS17-010渗透win7(32位)
  8. 可以获得索引值码_SEO优化可以为网站带来更高的业务销售额
  9. 转成数组_JavaScript之数组扁平化
  10. 线程中task取消_Rust Async: async-task源码分析
  11. install python 3.5.0_Mac 下安装Python3.5出现“python3-3.5.0 already installed, it's just not linked”错误...
  12. pdf转word python_Python实现PDF转Word
  13. OpenCV--读取图像中任意点的像素值,并显示坐标
  14. android:contentDescription 的用途
  15. hadoop 集群间数据迁移
  16. 【python基础语法】对象None
  17. bzoj4987: Tree(树形dp)
  18. 基于Python向Abaqus导入txt、dat数据(附abaqus中python二次开发课程)
  19. 分享128个简约模板PPT模板,总有一款适合你
  20. 怎么调html分辨率,屏幕分辨率怎么调

热门文章

  1. 【计蒜客 - 蓝桥训练】修建公路(贪心,或运算,dp)
  2. 【CodeForces - 271B 】Prime Matrix (素数,预处理打表,思维)
  3. 机器学习笔记(十四):异常检测
  4. 微博API接入初识【cxn专用】
  5. java poi 3.13_Java 读取Excl文件 (poi-3.13)
  6. php正文重复度,百度如何判断网页文章的重复度?两个页面相似度确认方法介绍...
  7. joptionpane java_Java JOptionPane
  8. matlab rootdir,Python cfg.ROOT_DIR属性代码示例
  9. kubelet内存异常分析
  10. 《Python Cookbook 3rd》笔记(2.19):实现一个简单的递归下降分析器