1.意图

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

2.别名

3.动机

考虑一个编译器。他将源程序表示为一个抽象语法树。该编译器须要在抽象语法上实施某些操作以进行“静态语义”分析,比如检查是否全部的变量都已经被定义了。

他也须要生成代码。由于它可能要定义很多操作以进行代码检查、代码优化、流程分析、检查变量是否在使用前被赋初值。等等。此外。还可使用抽象语法树进行优美格式打印、程序重构、code instrumentation以及对象进行多种度量。

4.适用性

下面情况使用Visitor模式:

  • 一个对象结构中包括非常多类对象,他们有不同的接口,而你想对这些对象实施一些依赖于其详细类的操作。

  • 须要对一个对象结构中的对象进行非常多不同的而且不相关的操作。而你想避免让这些操作”污染“这些对象的类。Visitor使得你能够将相关的操作集中起来定义在一个类中。当该对象结构被非常多应用共享时,用Visitor模式让每一个应用仅包括须要用到的操作。
  • 定义对象结构的类非常少改变,但常常须要在此基础上定义新的操作。改变对象结构类须要重定义对全部对象訪问者的接口,这可能须要非常大的代价。

    假设对象结构类常常改变,那么可能还是在这些类中定义这些操作比較好。

5.结构

訪问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。訪问者模式适用于数据结构相对稳定算法又易变化的系统。由于訪问者模式使得算法操作添加变得easy。若系统数据结构对象易于变化。常常有新的数据对象添加进来,则不适合使用訪问者模式。訪问者模式的长处是添加操作非常easy。由于添加操作意味着添加新的訪问者。訪问者模式将有关行为集中到一个訪问者对象中。其改变不影响系统数据结构。其缺点就是添加新的数据结构非常困难。—— From 百科

简单来说,訪问者模式就是一种分离对象数据结构与行为的方法,通过这样的分离,可达到为一个被訪问者动态加入新的操作而无需做其他的改动的效果。简单关系图:

6.代码演示样例

来看看原码:一个Visitor类。存放要訪问的对象。

实现代码:

状态结构:

public interface Visitor {
public void visit(Subject sub);
} public class MyVisitor implements Visitor { @Override
public void visit(Subject sub) {
System.out.println("visit the subject:"+sub.getSubject());
}
}

Subject类,accept方法。接受将要訪问它的对象。getSubject()获取将要被訪问的属性:

public interface Subject {
public void accept(Visitor visitor);
public String getSubject();
} public class MySubject implements Subject { @Override
public void accept(Visitor visitor) {
visitor.visit(this);
} @Override
public String getSubject() {
return "love";
}
}

測试类:

public class Test {

    public static void main(String[] args) {

        Visitor visitor = new MyVisitor();
Subject sub = new MySubject();
sub.accept(visitor);
}
}

输出:visit the subject:love

该模式适用场景:假设我们想为一个现有的类添加新功能。不得不考虑几个事情:1、新功能会不会与现有功能出现兼容性问题?2、以后会不会再须要加入?3、假设类不同意改动代码怎么办?面对这些问题,最好的解决方法就是使用訪问者模式。訪问者模式适用于数据结构相对稳定的系统,把数据结构和算法解耦。

7.相关模式

  • Composite模式:訪问者能够用于对一个由Composite模式定义的对象结构进行操作。
  • Interpreter模式:訪问者能够用于解释。

引用:

http://openhome.cc/Gossip/DesignPattern/DecoratorPattern.htm

http://item.jd.com/10057319.html

http://blog.csdn.net/zhangerqing/article/details/8239539

最新文章

  1. 谈一谈SQL Server中的执行计划缓存(上)
  2. php封装微信SDK
  3. ASP.NET MVC学习之模型绑定(1)
  4. 【MySQL】游标的具体使用详解
  5. taglib 自定义标签
  6. node.js在windows下的学习笔记(8)---进程管理Process
  7. 在Windows下用Eclipse+CDT+MinGW搭建C++开发平台
  8. go笔记-值传递、引用传递
  9. 抖音分享和授权(iOS)
  10. Luogu5245 【模板】多项式快速幂(多项式exp)
  11. 地图api
  12. 【转】Intellij IDEA使用总结
  13. chrome插件开发,易懂
  14. java学习之路-分享笔记20150327
  15. POJ 3580 SuperMemo (splay tree)
  16. vue页面开发遇到的坑,都是泪!src属性,freemarker取值
  17. jvm内存分部
  18. 笔记-python-float(‘inf’)
  19. Spring之3:BeanFactory、ApplicationContext、ApplicationContextAware区别
  20. HIbernate | 简单对象嵌套实践

热门文章

  1. Introspector
  2. vue的在子组件在使用iview库发现的问题
  3. Linux Mint 19.1将采用新的桌面布局
  4. Python, Django 性能分析工具的使用
  5. 03013_JDBC工具类
  6. sendfile复习
  7. swift 编译提前定义 --不知道怎么定义,可是能够#if
  8. jmeter名词解释之聚合报告
  9. 新手学,java使用分水岭算法进行图像切割(一)
  10. 转战Androidstudio之项目eclipse迁移