参考文章:

http://www.importnew.com/15561.html

定义:

封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

uml类图:

模式组成:

  • Vsitor :访问者的抽象角色。抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法中的参数定义哪些对象是可以被访问的。
  • ConcreteVsitor:访问者的具体实现。实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情。
  • Element:元素的抽象角色。接口或者抽象类,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。抽象元素一般有两类方法,一部分是本身的业务逻辑,另外就是允许接收哪类访问者来访问。
  • ConcreteElement:元素的具体实现。实现抽象元素类所声明的accept方法,通常都是visitor.visit(this),基本上已经形成一种定式了。

优点:

  • 符合单一职责原则:凡是适用访问者模式的场景中,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使用访问者模式符合单一职责原则
  • 扩展性良好:元素类可以通过接受不同的访问者来实现对不同操作的扩展。

缺点:

  • 增加新的元素类比较困难。

通过访问者模式的代码可以看到,在访问者类中,每一个元素类都有它对应的处理方法,也就是说,每增加一个元素类都需要修改访问者类(也包括访问者类的子类或者实现类),修改起来相当麻烦。也就是说,在元素类数目不确定的情况下,应该慎用访问者模式。所以,访问者模式比较适用于对已有功能的重构,比如说,一个项目的基本功能已经确定下来,元素类的数据已经基本确定下来不会变了,会变的只是这些元素内的相关操作,这时候,我们可以使用访问者模式对原有的代码进行重构一遍,这样一来,就可以在不修改各个元素类的情况下,对原有功能进行修改。

应用场景:

假如一个对象中存在着一些与本对象不相干(或者关系较弱)的操作,为了避免这些操作污染这个对象,则可以使用访问者模式来把这些操作封装到访问者中去。

扩展:

java的动态绑定与双分派

http://blog.csdn.net/zhengzhb/article/details/7496949

举个栗子:

(对账单定义不同的访问者。访问者老板关注的点是盈利总额。访问者会计关注的点是账单明细与工资明细是否匹配)

定义访问者的抽象角色

interface Visitor {
public void visit(Element element);
}

定义元素的抽象角色

interface Element {
public void accept(Visitor visitor);
}

定义元素的具体实现

class Bill implements Element {
public int totalGain = 500;
public boolean isMatchSalaryDetail = false; public int getTotalGain() {
return totalGain;
} public boolean isMatchSalaryDetail() {
return isMatchSalaryDetail;
} @Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

定义一个访问者

class Boss implements Visitor {
@Override
public void visit(Element element) {
Bill bill = (Bill) element;
if (bill.getTotalGain() < 3000) {
dosomething();
}
} public void dosomething() {
System.out.println("老板 发现盈利很低,很生气,准备全体降薪!");
}
}

定义一个访问者

class Accounting implements Visitor {
@Override
public void visit(Element element) {
Bill bill = (Bill) element;
if (!bill.isMatchSalaryDetail) {
dosomething();
}
}
public void dosomething() {
System.out.println("会计 发现账单明细与工资明细不匹配!立刻查账!");
}
}

客户端调用

public static void main(String[] args) {
Visitor boss = new Boss();
Visitor accounting = new Accounting();
Element bill=new Bill();
bill.accept(boss);
bill.accept(accounting);
}

输出

最新文章

  1. VS2013无法启动IIS Express Web的解决办法
  2. 《精通Hibernate:Java对象持久化技术详解》目录
  3. IOS开发之WIFI及IP相关
  4. SQL——存储过程实例 循环
  5. linux常用命令:1文件处理命令
  6. C++自定义异常处理
  7. 关于Windows8.1更新后Sql Server服务消失的处理办法
  8. copy指定目录下包括子目录中所有的文件
  9. SQL2005清空删除日志
  10. 关于使用easyui 中提示dialog is not a function的问题
  11. ☆ [POJ2411] Mondriaan&#39;s Dream 「状压DP」
  12. 一次基于Vue.Js的用户体验优化 (vue drag)
  13. 描述各自页面的 page
  14. OO Summary Ⅲ
  15. Css相册
  16. 推荐vue.js、layer.js、axios.js
  17. vue2.* 事件结合双向数据绑定、模块化以及封装Storage实现todolist 待办事项 已经完成 和进行中持久化 06
  18. java 移位
  19. PHP实现连接设备、通讯和发送命令的方法
  20. Codeforces Round #496 (Div. 3) E2 - Median on Segments (General Case Edition)

热门文章

  1. Scroller——startScroll、fling(惯性滑动)
  2. HttpUtils请求工具类
  3. java实现表达式求值 (20 分)-------非递归版
  4. Ansible入门笔记(3)之Playbook
  5. python工程化最佳实践
  6. Django之form主键
  7. LVS负载均衡部署
  8. Matplotlib同时绘制多张图片
  9. ubuntu坑(持续更新~)
  10. AHOI2014 奇怪的计算器 和 HDU5306 Gorgeous Sequence