概念:

  Visitor模式也叫访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作。

  访问者模式的应用示例

  比如有一个公园,有一到多个不同的组成部分;该公园存在多个访问者:清洁工A负责打扫公园的A部分,清洁工B负责打扫公园的B部分,公园的管理者负责检点各项事务是否完成,上级领导可以视察公园等等。也就是说,对于同一个公园,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间的推移而变化(行为的扩展性)。根据软件设计的开闭原则(对修改关闭,对扩展开放),我们怎么样实现这种需求呢?

  访问者模式的结构

  访问者模式的角色和职责

  1、 访问者角色(Visitor):为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。

  2、具体访问者角色(Concrete Visitor):实现每个由访问者角色(Visitor)声明的操作。

  3、元素角色(Element):定义一个Accept操作,它以一个访问者为参数。

  4、具体元素角色(Concrete Element):实现由元素角色提供的Accept操作。

  5、对象结构角色(Object Structure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合。

  下面,用代码来实现一下访问者模式

  首先,先新建一个公园的各个组成部分(因为有了各个组成部分才能有公园,所以我们先建各个组成部分,再建公园)

  新建一个公园各个部分的抽象类元素角色Element),需要传入一个访问者,一会后面会创建访问者

 /*
* 公园每一部分的抽象
*/
public interface ParkElement {
//用来接纳访问者
public void accept(Visitor visitor);
}

  再新建公园的各个部分,这是具体元素角色(Concrete Element)

  关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

 public class ParkA implements ParkElement{

     @Override
public void accept(Visitor visitor) {
visitor.visit(this);
} }
 public class ParkB implements ParkElement{

     @Override
public void accept(Visitor visitor) {
visitor.visit(this);
} }

  有了公园的各个部分,我们就可以开始新建公园了,这就是对象结构角色(Object Structure)

 /*
* 整个公园,其中包含了公园的各个部分
*/
public class Park implements ParkElement{
private ParkA parkA;
private ParkB parkB; public Park() {
super();
this.parkA = new ParkA();
this.parkB = new ParkB();
} @Override
public void accept(Visitor visitor) {
visitor.visit(this);
parkA.accept(visitor);
parkB.accept(visitor);
} }

  有了公园,我们就可以开始建造访问者了,先建造访问者角色(Visitor)

 /*
* 其中包含访问公园不同区域的重载方法,其中重载的参数Park,ParkA,PArkB,不仅可以获得公园的信息,还用来作为重载的条件
*/
public interface Visitor {
public void visit(Park park);
public void visit(ParkA parkA);
public void visit(ParkB parkB);
}

  然后在建造具体访问者角色,就是具体访问者角色(Concrete Visitor)

 /*
* 清洁工A负责公园A的清洁情况
*/
public class VisitorA implements Visitor{ @Override
public void visit(Park park) {
} @Override
public void visit(ParkA parkA) {
System.out.println("清洁工A完成了公园A的卫生");
} @Override
public void visit(ParkB parkB) {
} }
 /*
* 清洁工B负责公园B的清洁情况
*/
public class VisitorB implements Visitor{ @Override
public void visit(Park park) {
} @Override
public void visit(ParkA parkA) {
} @Override
public void visit(ParkB parkB) {
System.out.println("清洁工B完成了公园B的卫生");
} }
 /*
* 公园管理员负责检查整个公园的卫生情况
*/
public class VisitorManager implements Visitor{ @Override
public void visit(Park park) {
System.out.println("管理员:负责公园的卫生检查");
} @Override
public void visit(ParkA parkA) {
System.out.println("管理员:负责公园A部分的卫生检查");
} @Override
public void visit(ParkB parkB) {
System.out.println("管理员:负责公园B部分的卫生检查");
} }

  最后,新建一个客户端

 public class MainClass {
public static void main(String[] args) {
Park park = new Park(); Visitor visitorA = new VisitorA();
park.accept(visitorA); Visitor visitorB = new VisitorB();
park.accept(visitorB); VisitorManager visitorManager = new VisitorManager();
park.accept(visitorManager);
}
}

  结果:

  这样,一个访问者模式的例子就完成了,一定把上面的程序看懂

   访问者模式的使用意图:

  主要将数据结构与数据操作分离,解决了稳定的数据结构和易变的操作耦合问题。   

   访问者模式的使用场景:

  需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

  1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

  2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

   访问者模式的优缺点:

  优点:

  1、符合单一职责原则。

  2、优秀的扩展性。

  3、灵活性。

  缺点:

  1、具体元素对访问者公布细节,违反了迪米特原则。

  2、具体元素变更比较困难。

  3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

  注意事项:  

  访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

java设计模式-----24、访问者模式的更多相关文章

  1. 折腾Java设计模式之访问者模式

    博客原文地址:折腾Java设计模式之访问者模式 访问者模式 Represent an operation to be performed on the elements of an object st ...

  2. JAVA设计模式之访问者模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述访问者(Visitor)模式的: 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要 ...

  3. 15.java设计模式之访问者模式

    基本需求: 电脑需要键盘鼠标等固定的组件组成 现在分为个人,组织等去买电脑,而同一种组件对不同的人(访问者)做出不同的折扣,从而电脑的价格也不一样 传统的解决方法:在组件内部进行判断访问人的类型,从而 ...

  4. 由电脑专卖系统引发的Java设计模式:访问者模式

    目录 定义 意图 解决问题 何时使用 优缺点 结构 电脑专卖系统 定义 访问者模式是对象的行为型模式,它的目的是封装一些施加于某些数据结构元素之上的操作,一旦这些操作需要修改的话,接收这个操作的数据结 ...

  5. C#设计模式总结 C#设计模式(22)——访问者模式(Vistor Pattern) C#设计模式总结 .NET Core launch.json 简介 利用Bootstrap Paginator插件和knockout.js完成分页功能 图片在线裁剪和图片上传总结 循序渐进学.Net Core Web Api开发系列【2】:利用Swagger调试WebApi

    C#设计模式总结 一. 设计原则 使用设计模式的根本原因是适应变化,提高代码复用率,使软件更具有可维护性和可扩展性.并且,在进行设计的时候,也需要遵循以下几个原则:单一职责原则.开放封闭原则.里氏代替 ...

  6. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  7. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  8. 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern)

    原文:乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) 作者:webabc ...

  9. JAVA设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

  10. 折腾Java设计模式之建造者模式

    博文原址:折腾Java设计模式之建造者模式 建造者模式 Separate the construction of a complex object from its representation, a ...

随机推荐

  1. 564. Find the Closest Palindrome

    Given an integer n, find the closest integer (not including itself), which is a palindrome. The 'clo ...

  2. python项目实现配置统一管理的方法

    一个比较大的项目总是会涉及到很多的参数,最好的方法就是在一个地方统一管理这些参数.最近看了不少的python项目,总结了两种很有意思的配置管理方法. 第一种 基于easydict实现的配置管理 首先需 ...

  3. Linux巩固记录(5) hadoop 2.7.4下自己编译代码并运行MapReduce程序

    程序代码为 ~\hadoop-2.7.4\share\hadoop\mapreduce\sources\hadoop-mapreduce-examples-2.7.4-sources\org\apac ...

  4. 在ubuntu中我们使用sudo apt-get install 或者dpkg -i *.deb安装软件时,常常提示“有未能满足的依赖关系“,解决方法

    很早之前在ubuntu安装软件时遇到的问题,今天打开ubuntu看到了,总结如下: 在ubuntu中我们使用sudo apt-get install 或者dpkg -i *.deb安装软件常常提示“有 ...

  5. Win10 安装 digits

    安装caffe配置python接口 接下来就按照官方教程来安装了... 1. If the installation process complains compiler not found, you ...

  6. postgresql-int,bigint,numeric效率测试

    在postgresql9.5的时候做过一个测试就是sum()的效率最终的测试结果是sum(int)>sum(numeric)>sum(bigint)当时比较诧异为啥sum(bigint)效 ...

  7. 5_Python OOP

    1. 实例属性和类属性        (1) 实例属性在构造函数__init__中定义,定义时以self作为前缀,只能通过实例名访问        (2) 类属性在类中方法之外单独定义,还可以在程序中 ...

  8. 基于 WiFi ( Wireless Fidelity) 的室内定位技术

    系统的拓扑结构 基于信号强度的定位技术(RSSI, Received Signal Strength Indication) 无线信号的信号强度随着传播距离的增加而衰减,接收方与发送方离得越近, 则接 ...

  9. VMware虚拟机克隆Linux(CentOS)系统后找不到eth0网卡的问题(图文详解)

     问题现象: 有时候,会使用VMware虚拟机的的克隆功能,快速的复制已安装好的Linux系统. 可是克隆完之后,会发现没有eth0网卡. 解决办法: 1.编辑/etc/udev/rules.d/70 ...

  10. 超漂亮的CSS3按钮制作教程分享

    要求 必备知识 基本了解CSS语法,初步了解CSS3语法知识. 开发环境 Adobe Dreamweaver CS6/Chrome浏览器 演示地址 演示地址 利用CSS3属性制作按钮,我们只需要用到G ...