一、是什么?
这是一个比较复杂且初理解比较困难的模式,先举个例子,帮助理解这个模式。
例子: 无人机群表演的例子,想让无人机群组合成不同的形状,不需要换一批无人机,我们只需要改变无人机群的代码就可以了,不用改变无人机的硬件(高度器和方向器),输入不同的代码,无人机就可以做不同的动作。
定义: 封装一些作用于某种数据结构(无人机硬件)的各元素(高度器)的操作(高低),它可以在不改变数据结构的前提下定义作用于这些元素的新的操作(代码)。
这个例子中,【数据结构】:无人机或无人机硬件;【各元素】:高度器和方向器;【操作】:飞多高或者往哪飞;【代码】:访问者。
二、类图
- Code:是抽象访问者
- ConcreteCode:是一个具体的访问者 实现每个由Code声明的操作,是每个操作实现的部分
- UAVGroup:无人机群,能枚举他的元素,可以提供一个高层的接口,用来允许访问者访问元素
- UAV:无人机抽象,声明了公共方法,接收一个访问者对象
- LeaderUAV:为具体的元素,实现了light方法
转换成我们的例子
三、例子实现
UAV
:抽象无人机,定义了无人机的公共属性和公共行为。其中executeCode用于执行代码,让代码访问控制无人机。
public abstract class UAV {
// 无人机编号
public int id;
/**
* 灯光
*/
public abstract void light();
/**
* 上升高度
*
* @param height
*/
public void riseHeight(int height) {
System.out.println("【"+ this.id +"】 号上升" + height + "米");
}
/**
* 下降高度
*
* @param height
*/
public void downHeight(int height) {
System.out.println("【"+ this.id +"】 号下降" + height + "米");
};
/**
* 改变方向距离
*
* @param direction 方向
* @param distance 距离
*/
public void changeDirection(String direction, int distance) {
// 打印往哪个方向飞多少米
System.out.println("【"+ this.id +"】 号往" + direction + "方向飞" + direction + "米");
}
/**
* 让代码控制自己
*
* @param code
*/
public void executeCode(Code code) {
code.controlUAV(this);
}
}
LeaderUAV
:具体的无人机,领头无人机。
public class LeaderUAV extends UAV{
public LeaderUAV(int id) {
this.id = id;
light();
}
@Override
public void light() {
System.out.println("【"+ this.id +"】 号开启迪斯科灯");
}
}
GeneralUAV
:具体的无人机,普通无人机。
public class GeneralUAV extends UAV{
public GeneralUAV(int id) {
this.id = id;
light();
}
@Override
public void light() {
System.out.println("【"+ this.id +"】 号开启绿光");
}
}
UAVGroup
:无人机群,提供访问者访问的方法。
public class UAVGroup extends ArrayList<UAV> {
/**
* 无人机群执行代码
*
* @param code
*/
public void executeCode(Code code) {
this.forEach(uav -> uav.executeCode(code));
}
}
Code
:代码抽象。
public abstract class Code {
// 控制无人机
public abstract void controlUAV(UAV uav);
}
ConcreteCode$1
:具体的代码
public class ConcreteCode$1 extends Code{
@Override
public void controlUAV(UAV uav) {
if (uav instanceof LeaderUAV) {
// 上升20米
uav.riseHeight(20);
} else {
// 往北飞五米
uav.changeDirection("北", new Random().nextInt(50));
// 上升五米
uav.riseHeight(10);
// 再下降五米
uav.d ownHeight(5);
}
}
}
Client
:环境类,使用模式的地方。
public class Client {
public static void main(String[] args) {
UAVGroup uavs = new UAVGroup();
uavs.add(new LeaderUAV(1));
uavs.add(new GeneralUAV(2));
uavs.add(new GeneralUAV(3));
uavs.add(new GeneralUAV(4));
Code code = new ConcreteCode$1();
uavs.executeCode(code);
}
}
执行结果:
无人机集群想展示不同的表演,只需要将new ConcreteCode$1()
改成其他的代码即可。
四、优缺点
优点:
- 符合单一职责原则
- 扩展性好
- 灵活性好
缺点:
因为本文中访问者依赖的是抽象,所以不存在被访者种类扩展难和违背依赖倒置原则的问题。