java的visitor模式_java设计模式(二十一)访问者模式(Visitor)

介绍

访问者模式(Visitor Pattern):表示一个作用于某对象结构中的各元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。

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

关系图:

831c223fe76f4cbcdba5e54ff8fc18c2.png

Visitor接口:存放要访问的对象1

2

3public interface{

public void visit(Subject sub);

}

实现类:1

2

3

4

5

6public class MyVisitor implements{

public void visit(Subject sub){

System.out.println("visit the subject:"+sub.getSubject());

}

}

Subject接口:accept方法,接受将要访问它的对象,getSubject()获取将要被访问的属性1

2

3

4public interface Subject{

public void accept(Visitor visitor);

public String getSubject();

}

实现类:1

2

3

4

5

6

7

8

9

10

11public class MySubject implements Subject{

public void accept(Visitor visitor){

visitor.visit(this);

}

public String getSubject(){

return "love";

}

}

测试类:1

2

3

4

5

6

7

8public class Test{

public static void main(String[] args){

Visitor visitor = new MyVisitor();

Subject sub = new MySubject();

sub.accept(visitor);

}

}

该模式适用场景:如果我们想为一个现有的类增加新功能,不得不考虑几个事情:新功能会不会与现有功能出现兼容性问题?

以后会不会再需要添加?

如果类不允许修改代码怎么办?

面对这些问题,最好的解决方法就是使用访问者模式,访问者模式适用于数据结构相对稳定的系统,把数据结构和算法解耦

扩展

1. 模式动机在实际使用时,对同一集合对象的操作并不是唯一的,对相同的元素对象可能存在多种不同的操作方式。而且这些操作方式并不稳定,可能还需要增加新的操作,以满足新的业务需求。此时,访问者模式就是一个值得考虑的解决方案。

访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式。

2. 模式结构

f89069009a08555f9acf441f6256cc6b.png

访问者模式包含如下角色:Vistor: 抽象访问者

ConcreteVisitor: 具体访问者

Element: 抽象元素

ConcreteElement: 具体元素

ObjectStructure: 对象结构

3. 模式分析访问者模式中对象结构存储了不同类型的元素对象,以供不同访问者访问。

访问者模式包括两个层次结构,一个是访问者层次结构,提供了抽象访问者和具体访问者,一个是元素层次结构,提供了抽象元素和具体元素。

相同的访问者可以以不同的方式访问不同的元素,相同的元素可以接受不同访问者以不同访问方式访问。在访问者模式中,增加新的访问者无须修改原有系统,系统具有较好的可扩展性

典型的抽象访问者类代码:1

2

3

4

5

6

7public abstract class{

public abstract void visit(ConcreteElementA elementA);

public abstract void visit(ConcreteElementB elementB);

public void visit(ConcreteElementC elementC){

//元素ConcreteElementC操作代码

}

}

典型的具体访问者类代码:1

2

3

4

5

6

7

8public class ConcreteVisitor extends{

public void visit(ConcreteElementA elementA){

//元素ConcreteElementA操作代码

}

public void visit(ConcreteElementB elementB){

//元素ConcreteElementB操作代码

}

}

典型的抽象元素类代码:1

2

3public interface Element{

public void accept(Visitor visitor);

}

具体元素类代码:1

2

3

4

5

6

7

8

9public class ConcreteElementA implements Element{

public void accept(Visitor visitor){

visitor.visit(this);

}

public void operationA(){

//业务方法

}

}

典型的对象结构类代码:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16public class ObjectStructure{

private ArrayList list=new ArrayList();

public void accept(Visitor visitor){

Iterator i=list.iterator();

while(i.hasNext()) {

((Element)i.next()).accept(visitor);

}

}

public void addElement(Element element){

list.add(element);

}

public void removeElement(Element element){

list.remove(element);

}

}

4. 适用场景一个对象结构包含很多类型的对象,希望对这些对象实施一些依赖其具体类型的操作。在访问者中针对每一种具体的类型都提供了一个访问操作,不同类型的对象可以有不同的访问操作。

需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作污染这些对象的类,也不希望在增加新操作时修改这些类。访问者模式使得我们可以将相关的访问操作集中起来定义在访问者类中,对象结构可以被多个不同的访问者类所使用,将对象本身与对象的访问操作分离。

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

5. 模式应用在一些编译器的设计中运用了访问者模式,程序代码是被访问的对象,它包括变量定义、变量赋值、逻辑运算、算术运算等语句,编译器需要对代码进行分析,如检查变量是否定义、变量是否赋值、算术运算是否合法等,可以将不同的操作封装在不同的类中,如检查变量定义的类、检查变量赋值的类、检查算术运算是否合法的类,这些类就是具体访问者,可以访问程序代码中不同类型的语句。在编译过程中除了代码分析外,还包含代码优化、空间分配和代码生成等部分,也可以将每一个不同编译阶段的操作封装到了跟该阶段有关的一个访问者类中。

在常用的Java XML处理技术DOM4J中,可以通过访问者模式的方式来读取并解析XML文档,VisitorSupport是DOM4J提供的Visitor接口的默认适配器,具体访问者只需继承VisitorSupport类即可。1

2

3

4

5

6

7

8public class MyVisitor extends VisitorSupport{

public void visit(Element element){

System.out.println(element.getName());

}

public void visit(Attribute attr){

System.out.println(attr.getName());

}

}

6. 模式扩展与其他模式联用由于访问者模式需要对对象结构进行操作,而对象结构本身是一个元素对象的集合,因此访问者模式经常需要与迭代器模式联用,在对象结构中使用迭代器来遍历元素对象。

在访问者模式中,元素对象可能存在容器对象和叶子对象,因此可以结合组合模式来进行设计。

访问者模式以一种倾斜的方式支持开闭原则,增加新的访问者方便,但是增加新的元素很困难。

7. 模式优缺点优点使得增加新的访问操作变得很容易。

将有关元素对象的访问行为集中到一个访问者对象中,而不是分散到一个个的元素类中。

可以跨过类的等级结构访问属于不同的等级结构的元素类。

让用户能够在不修改现有类层次结构的情况下,定义该类层次结构的操作。

缺点增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,违背了开闭原则的要求。

破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/551384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python多元函数求极小值_使用遗传算法求二元函数的最小值

二元函数为yx1^2x2^2,x∈[-5,5]NIND121; %初始种群的个数(Number of individuals)NVAR2; %一个染色体(个体)有多少基因PRECI20; %变量的二进制位数(Precision of variables)MAXGEN200; %最大遗传代数(Maximum number of generations)GGAP0.8; %代沟(Generation gap)&#xff0c…

testlink mysql配置_TestLink安装配置手册

TestLink安装配置手册范围本文仅作为安装和配置TestLink的参考文档。本文的第一部分为TestLink的安装步骤,第二部分是TestLink的配置方法。本文和其他相关文档可在中寻求帮助一般TestLink安装的步骤如下:1.下载TestLink2.解压文件3.创建数据库4.导入缺省…

python matlibplot绘制矩阵_matplotlib.pyplot.matshow 矩阵可视化实例

这是一个绘制矩阵的函数。用matshow绘制矩阵的例子:import matplotlib.pyplot as pltimport numpy as npdef samplemat(dims):"""Make a matrix with all zeros and increasing elements on the diagonal"""aa np.zeros(dims)for i …

如果有一个人在我创业之前告诉我这些

听别人的个人经历,并持保留态度,结合自己用来参考。 首先验证想法。不要浪费时间来建造无人需要的东西。扼杀你的自我。 创业内容不在于自我,而是关于用户。必须去想用户想要什么,而不是我想要什么的。不要盲目躺平顺从投资者&…

时分秒 java_JAVA 时分秒累加

一、简介有个需求是,累加通话时长,把上次通话时长加上本次通话时长,依次累加。二、实现Testpublic void TestA() throws ParseException {SimpleDateFormat myFormatter new SimpleDateFormat("HH:mm:ss");SimpleDateFormat forma…

python插件化设计_python - 插件化编程

引用2018-11-06 python插件式框架开发https://www.jianshu.com/p/a472f44c7161python 优雅地实现插件架构https://www.cnblogs.com/hhh5460/p/6681363.html一. classmethod function装饰器1.1 项目结构├─ project├─ run.py├─ app├─ __init__.py├─ main.py├─ platf…

java 如何实现对象克隆_Java对象克隆

Java不提供克隆(复制)对象的自动机制。克隆对象意味着逐位复制对象的内容。要支持克隆操作,请在类中实现clone()方法。Object类中的clone()方法的声明如下:protected Object clone() throws CloneNotSupportedExceptionclone()方法声明为protected。 因此…

python 默认配置文件_python各类配置文件写法

1. csv文件csv:Comma-Separated Values半结构化数据逗号分割值,可以使用office或者wps打开。模块:csvcsv.reader(csvfile,dialect’excel’,**fmtparams)csv.writer(csvfile,dialect’excel’,**fmtparams)返回一个DictWriter实例。主要支持的…

java mvc建包结构_Java SSM框架的配置方法、MVC结构的分析、响应的流程

今天头一次配置成功一个SSM框架,兴奋之余,还应该从使用的角度,将整个ssm配置的方法,配置的原因,认真的分析一下。在结束了对SSM框架简单的分析之后,就要开始回归基础,全面的认真复习。所以这个文…

英特尔显示器音频_英特尔也玩马甲?有关USB TypeC的冷知识你了解多少

随着Type-C接口的不断发展,这个接口也成为越来越多设备的标配,除了出现在手机、平板电脑和笔记本电脑等移动设备上,显卡这样的设备也开始配备Type-C接口了,本周末,小编为大家收集了一些有关Type-C接口的冷知识&#xf…

java drawingpanel_Java DrawingPanel.getHeight方法代码示例

import org.opensourcephysics.display.DrawingPanel; //导入方法依赖的package包/类/*** Paint the contour.* param g*/public synchronized void draw(DrawingPanel panel, Graphics g) {if(!visible||(griddatanull)) {return;}if(!autoscaleZ && showColoredLevel…

python激活虚拟环境source不是内部或外部_激活虚拟环境的问题

F:\sdk\imooc_request>virtualenv envname --no-setuptools --no-pip --no-wheelUsing base prefix f:\\编程\\pycharmNew python executable in F:\sdk\imooc_request\envname\Scripts\python.exeF:\sdk\imooc_request>source .env/bin/activatesource 不是内部或外部命…

如何允许网页中的编辑器访问剪切板_Vditor下一代的 Markdown 编辑器,为未来而构建...

❝Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得(富文本)、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React、Angular,提供桌面版❞Markdown背景随着 Markdown 排版方式的普及&…

java ocsp请求_java – 客户端证书上的OCSP吊销

如果仅使用客户端的java.security.cert.X509Certificate,如何使用OCSP手动检查java中的证书撤销状态?我看不清楚这样做的明确方法.或者,我可以让tomcat自动为我做,你怎么知道你的解决方案是真的?解决方法:我发现了一个最优秀的解决方案/**54 * This is a…

java模型给泛型_【一天一个基础系列】- java之泛型篇

java 5以后,java引入了“参数化类型”的概念,允许程序在创建集合时指定集合元素的类型java 7之前,如果使用带泛型的接口、类定义变量,那么调用构造器创建对象时构造器的后面也必须带泛型比如//java 7之前List list new ArrayList…

mpython掌控板作品_第1课 Arduino micro:bit 掌控板 创客教育常用的3类主控板

有很多朋友想学习创客,问我怎么学习。我建议他先百度一下“创客”,看看有什么感觉。结果还是很懵,五花八门,什么都有,找不到核心。简单理解,就是以前讲的DIY,自己动手,制作一个东西。…

redis启动没反应_Promethues如何针对Redis进行监控

需求:采用redis_exporter 收集数据,promethus采集redis_exporter数据,granfana展示数据一、简易安装redisyum install -y redisrpm -qa |grep redislsof -i :6379rpm -ql redissystemctl start redis找到配置文件/etc/redis.conf,修改 requir…

网上书店管理系统java部分代码_网上书店管理系统 java语言

【实例简介】整个系统,包括数据库,安装上就能用,非常适合做课程设计的作业或者毕业设计的作业【实例截图】【核心代码】OnLineBookStore└── OnLineBookStore├── WebRoot│ ├── META-INF│ │ └── MANIFEST.MF│ ├── W…

java自定义标签遍历_自定义标签 - CarlDing的个人页面 - OSCHINA - 中文开源技术交流社区...

EL的不足,由JSTL来加强 -> 自定义标签来实现。1:自定义标签1:自定义标签也是类。2:让用户在JSP页面使用,不引用Java代码的情况下,调用Java代码。2:标签开的类的继承关系3:快速的…

python宏替换_简单的宏替换

简单的宏替换1.宏定义必须写在第一次使用该宏定义的代码之前;2.宏定义不是以分号结束的3.#define string1 string2 之间至少要有一个空格4.string 1称为宏,string2 称为宏扩展5. 宏名用大写的字母表示是一个习惯6.使用宏的好处:a 简化程序的书…