Java 设计模式——访问者模式(行为型设计模式)

简介

访问者模式(VisitorPattern),顾名思义使用了这个模式后就可以在不修改已有程序结构的前提下,通过添加额外的访问者来完成对已有代码功能的提升,它属于行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。
其主要目的是将数据结构与数据操作分离。

访问者模式可以说是设计模式中最难以理解的一个模式,因为相比其它模式而言,它过于”绕“了。但是我们可以通过生活中的一些例子来理解它,比如家里来了客人,客人就是访问者,他可以做一些事情,但是又不能做全部的事情; 又或者说去网吧上网的小明,小明也是访问者,他可以在网吧玩游戏、看视频、听音乐等等,但是不能破坏网吧中的设备等等。按照这么理解,我们大概就可以知道访问者模式主要是做什么了。

访问者模式主要由这五个角色组成,抽象访问者(Visitor)、具体访问者(ConcreteVisitor)、抽象节点(Node)、具体节点(ConcreteNode)和结构对象(ObjectStructure)。

  • 抽象访问者(Visitor)角色:声明了一个或者多个方法操作,形成所有的具体访问者角色必须实现的接口。
  • 具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。
  • 抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参数。
  • 具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。
  • 结构对象(ObjectStructure)角色:有如下的责任,可以遍历结构中的所有元素

示例图如下:
在这里插入图片描述
这里为了方便理解,我们使用一个简单的示例来加以说明。
图书馆有一台电脑,有两个账户,其中一个是管理员的账户,拥有所有权限,但是设置了密码;另一个账户是不需要密码,但是只能玩游戏和看图片。张三和李四先后使用了这台电脑,那么他们就可以当作是访问者。
那么我们便可以根据这里例子来使用访问者模式进行开发,首先定义一个抽象的访问者,拥有玩游戏和看图片的方法;然后再定义一个抽象节点电脑,接受这个请求。
那么这个抽象类的代码如下:


interface Visitor {
   void visit(Games games);
   void visit(Photos photos);
}

interface Computer {
   void accept(Visitor visitor);
}

定义好该抽象类之后,我们需要设计不同的访问者对节点进行不同的处理。并且需要设计具体节点类实现刚刚抽象节点的方法。

那么代码如下:

class ZhangSan implements Visitor {
   @Override
   public void visit(Games games) {
   	games.play();
   }

   @Override
   public void visit(Photos photos) {
   	photos.watch();
   }
}

class LiSi implements Visitor {
   @Override
   public void visit(Games games) {
   	games.play();
   }
   @Override
   public void visit(Photos photos) {
   	photos.watch();
   }
}

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

   public void play() {
   	System.out.println("play lol");
   }
}

class Photos implements Computer {
   @Override
   public void accept(Visitor visitor) {
   	visitor.visit(this);
   }
   
   public void watch() {
   	System.out.println("watch scenery photo");
   }
}


最后我们还需要定义一个结构对象角色,提供一个的接口并允许该访问者进行访问,它可以对这些角色进行增加、修改或删除等操作和遍历。
代码如下:

class ObjectStructure {

	private List<Computer> computers = new ArrayList<Computer>();

	public void action(Visitor visitor) {
		computers.forEach(c -> {
			c.accept(visitor);
		});
	}
	public void add(Computer computer) {
		computers.add(computer);
	}
}

编写好之后,那么我们来进行测试。
测试代码如下:


public static void main(String[] args) {
   	// 创建一个结构对象
   	ObjectStructure os = new ObjectStructure();
   	// 给结构增加一个节点
   	os.add(new Games());
   	// 给结构增加一个节点
   	os.add(new Photos());
   	// 创建一个访问者
   	Visitor visitor = new ZhangSan();
   	os.action(visitor);

}


输出结果:

play lol
watch scenery photo

访问者模式优点:

扩展性好,可以在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能;
符合单一职责原则,通过访问者将无关的行为分离,使职责单一;

访问者模式缺点:

违反了迪米特原则,因为具体元素对访问者公布细节;
违反了依赖倒置原则,依赖了具体类,没有依赖抽象;
对象结构变化困难,若对象结构发生了改变,访问者的接口和访问者的实现也都要发生相应的改变;

使用场景:

对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作;
需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java设计模式行为模式共有11种,它们分别是策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式介者模式和解释器模式。这些行为模式涉及到对象之间的交互和通信,用于解决不同对象之间的行为问题。其,策略模式用于封装一系列的算法,让算法可以动态切换;模板方法模式用于定义算法的骨架,具体的实现由子类决定;观察者模式用于定义对象之间的一对多的依赖关系,当一个对象状态发生改变时,所有依赖该对象的对象都会收到通知;迭代器模式用于遍历集合对象的元素,而不暴露集合的内部结构;任链模式用于将请求的发送者和接收者解耦,每个接收者都可以选择处理请求或者将请求传递给下一个接收者;命令模式用于将请求封装成对象,从而可以更灵活地进行参数化和传递;备忘录模式用于保存和恢复对象的状态,以便在需要时可以回滚到之前的状态;状态模式用于根据对象的内部状态改变其行为访问者模式用于将数据结构和操作分离,从而可以在不修改数据结构的情况下定义新的操作;介者模式用于解耦多个对象之间的交互,使得各个对象可以独立地改变其行为;解释器模式用于定义一种语言的文法,并解释语言的表达式。这些行为模式可以在不同场景下使用,根据具体的需求选择合适的模式来解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不能吃辣的JAVA程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值