举例讲解设计模式中的访问者模式在Java编程中的运用
作者:匆忙拥挤repeat 发布时间:2022-04-04 08:00:45
访问者(Visitor)模式:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。访问者模式的结构图如下:
通过上图可以看到他有如下角色:
抽象访问者(Visitor)角色:定义接口,声明一个或多个访问操作。
具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象元素(Visitable)角色:声明一个接受操作,接受一个访问者对象作为一个参数。
具体元素结点(ConcreteElement)角色:实现抽象结点所规定的接受操作。
数据结构对象(ObjectStructure)角色:可以遍历结构中的所有元素,提供一个接口让访问者对象都可以访问每一个元素。
模拟代码如下:
interface Visitor {
void visit(Gladiolus g);
void visit(Chrysanthemum c);
}
// concrete visitor 名称访问
class StringVisitor implements Visitor {
String s;
public String toString() {
return s;
}
public void visit(Gladiolus g) {
s = "Gladiolus";
}
public void visit(Chrysanthemum c) {
s = "Chrysanthemum";
}
}
// concrete visitor 蜜蜂访问
class BeeVisitor implements Visitor {
public void visit(Gladiolus g) {
System.out.println("蜜蜂 来 访问 Gladiolus");
}
public void visit(Chrysanthemum c) {
System.out.println("蜜蜂 来 访问 Chrysanthemum");
}
}
interface Flower {
void accept(Visitor v);
}
/*
* concrete element 菊花
*/
class Chrysanthemum implements Flower {
public void accept(Visitor v) {
v.visit(this);
}
}
// concrete element 剑兰
class Gladiolus implements Flower {
public void accept(Visitor v) {
v.visit(this);
}
}
//这是Flower一个对象生成器
class FlowerGenerator {
private static Random rand = new Random();
public static Flower newFlower() {
switch (rand.nextInt(2)) {
default:
case 0:
return new Gladiolus();
case 1:
return new Chrysanthemum();
}
}
}
public class Test {
/*
* 首先在客户端先获得一个具体的访问者角色 遍历对象结构 对每一个元素调用accept方法,将具体访问者角色传入 这样就完成了整个过程
*/
public static void main(String args[]) {
List<Flower> flowers = new ArrayList<Flower>();
for (int i = 0; i < 10; i++)
flowers.add(FlowerGenerator.newFlower());
Visitor visitor = new StringVisitor();
Iterator<Flower> iterator = flowers.iterator();
while (iterator.hasNext()) {
iterator.next().accept(visitor);
System.out.println(visitor);
}
System.out.println("---------------");
/*
* 一个新的访问行为 :BeeVisitor 蜜蜂访问
*/
Visitor visitor2 = new BeeVisitor();
for (Flower flower : flowers) {
flower.accept(visitor2);
}
}
}
结果:
Gladiolus
Chrysanthemum
Chrysanthemum
Gladiolus
Chrysanthemum
Chrysanthemum
Chrysanthemum
Chrysanthemum
Gladiolus
Gladiolus
---------------
蜜蜂 来 访问 Gladiolus
蜜蜂 来 访问 Chrysanthemum
蜜蜂 来 访问 Chrysanthemum
蜜蜂 来 访问 Gladiolus
蜜蜂 来 访问 Chrysanthemum
蜜蜂 来 访问 Chrysanthemum
蜜蜂 来 访问 Chrysanthemum
蜜蜂 来 访问 Chrysanthemum
蜜蜂 来 访问 Gladiolus
蜜蜂 来 访问 Gladiolus
有以下情形可以考虑使用访问者模式:
1、一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。
3、当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
4、 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
这些个人看来都是建议,项目中还要具体问题具体分析了。


猜你喜欢
- 想问下这是什么情况。在导入一个maven项目时只有一个finish,点击完finish后没有任何反应。。。各位大佬给看下这是什么问题。急,在
- 什么是EurekaNetflix Eureka 是一款由 Netflix 开源的基于 REST 服务的注册中心,用于提供服务发现功能。Spr
- 实验环境hadoop版本:3.3.2jdk版本:1.8hadoop安装系统:ubuntu18.04编程环境:IDEA编程主机:windows
- 无论是Android开发或者是其他移动平台的开发,ListView肯定是一个大咖,那么对ListView的操作肯定是不会少的,上一篇博客介绍
- 问题描述Feign 在请求时是不会将 request 的请求头带着请求的,导致假如 Feign 调用的接口需要请求头的信息,比如当前用户的
- Hibernate中有HQL查询语法。但我们用得比较熟的还是数SQL语句,那么应该怎么来让Hibernate支持SQL呢?这个不用我们去考虑
- 数据库表结构departmentemployee要求一现在的要求是输入 id 把 employee 表的对应员工数据查询出来,并且查询出该员
- 本文实例讲述了java实现基于SMTP发送邮件的方法。分享给大家供大家参考。具体实现方法如下:import java.util.Date;i
- 前言最近在学习Kotlin这门语言,在项目开发中,运用到了单例模式。因为其表达方式与Java是不同的。所以对不同单例模式的实现进行了分别探讨
- 目录关于日志级别为什么选用log4j2排除 spring-boot 自带的 logback 依赖添加 log4j2 依赖配置文件节点解析根节
- package 移位运算;public class 移位运算 { public static void main(String[] args
- 本文实例为大家分享了Android自定义EditText实现登录界面的具体代码,供大家参考,具体内容如下先看效果图:自定义edittext
- 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。步骤为:1.从数
- 目录基本用法基于接口的 * 基于类的 * 异步函数拦截Autofac 集成基于接口的 * 基于类的 * 异步函数拦截Castle 是 200
- 本文实例讲述了Android开发实现删除联系人通话记录的方法。分享给大家供大家参考,具体如下:1. 负责存放呼叫记录的内容提供者源码在 Co
- FragmentManager 为了管理Activity中的fragments,需要使用FragmentManager. 为了得到它,需要调
- 获取resources文件路径背景在SpringBoot项目中,需要获取resources文件的路径,网上找了好多文章都不行,后面还是结合官
- 开始研究android开发,搭建开发环境的时候就出了问题……果然是好事多磨~ 安装了jdk,配置环境变量,安装了完整版的adt、创建了hel
- 现象说明maven的java项目,测试用例和main所在的源码文件均符合缺省写法和格式,但是在使用mvn clean sonar:sonar
- 一、返回一般数据类型比如要根据 id 属性获得数据库中的某个字段值。mapper 接口:// 根据 id 获得数据库中的 username