概念:

  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. Token的生成和检验

    package TestToken; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt. ...

  2. 【062有新题】OCP 12c 062出现大量之前没有的新考题-16

    choose one Which users are created and can be used for database and host management of your DBaaS da ...

  3. UICollectionView设置首个cell默认选中

    设置UICollectionView中某个cell的默认选中,刚开始为追求性能,采用同一个cellId去标识UICollectionViewCell,却由于cell的重用会导致之前选中的cell在被重 ...

  4. 【flex】学习笔记/总结

    CSS3 flex布局 查看兼容情况: caniuse.com 盒子模型: content-box:平时普通盒子模型,padding/border 会使盒子变大 向外扩展 border-box:盒子模 ...

  5. D02-R语言基础学习

    R语言基础学习——D02 20190423内容纲要: 1.前言 2.向量操作 (1)常规操作 (2)不定长向量计算 (3)序列 (4)向量的删除与保留 3.列表详解 (1)列表的索引 (2)列表得元素 ...

  6. python3处理json数据

    获取actuator的值 [root@mongo_rs1 tmp]# cat test.py import requests import json url = 'http://wxtest.mayo ...

  7. (转)python3-staticmethod与classmethod

    原文:https://blog.csdn.net/youngbit007/article/details/68957848 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...

  8. 【java初探】——格式化字符串

    String 类的静态方法format()方法用于创建格式化字符串,format()方法有两种重载形式: format(String fromat,Object...args) 该方法使用指定的格式字 ...

  9. Normal Map中的值, Tangent Space, 求算 Tangent 与 Binormal 与 TBN Matrix

      - Normal Map中的值 -   有没有想过,Normal Map(法线贴图)为什么看上去都是“偏蓝色”的?这是因为,在map中存储的值都是在Tangent Space(切空间)下的.比如, ...

  10. java虚拟机学习-Java常量池理解与总结(13-2)

    一.相关概念 什么是常量用final修饰的成员变量表示常量,值一旦给定就无法改变!final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. Class文件中的常量池在Clas ...