举例讲解设计模式中的访问者模式在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、 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
这些个人看来都是建议,项目中还要具体问题具体分析了。
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java动态获取实现某个接口下所有的实现类对象集合
基于Java利用static实现单例模式
android 使用Xml文件定义Shape方式
![](https://img.aspxhome.com/file/2023/5/102585_0s.jpg)
解决Spring Cloud feign GET请求无法用实体传参的问题
解决SpringMVC Controller 接收页面传递的中文参数出现乱码的问题
![](https://img.aspxhome.com/file/2023/9/86709_0s.jpg)
C#私有构造函数使用示例
Android通过应用程序创建快捷方式的方法
![](https://img.aspxhome.com/file/2023/0/98630_0s.png)
C#中ListView控件实现窗体代码
JAVA用递归实现全排列算法的示例代码
一文搞懂JMeter engine中HashTree的配置问题
![](https://img.aspxhome.com/file/2023/2/82022_0s.jpg)
Mybatis结果生成键值对的实例代码
C++中左值和右值的区别详解
![](https://img.aspxhome.com/file/2023/4/109774_0s.png)
在maven工程里运行java main方法
java将一个目录下的所有文件复制n次
![](https://img.aspxhome.com/file/2023/0/75680_0s.jpg)
C#文件和字节流的转换方法
Java编程实现生成给定范围内不重复随机数的方法小结
Java多线程事务回滚@Transactional失效处理方案
![](https://img.aspxhome.com/file/2023/2/82312_0s.png)
javamail 发送邮件的实例代码分享
Springboot @Validated和@Valid的区别及使用详解
![](https://img.aspxhome.com/file/2023/6/64916_0s.png)