访问者模式
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
介绍
意图:主要将数据结构与数据操作分离。
主要解决:稳定的数据结构和易变的操作耦合问题。
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。
如何解决:在被访问的类里面加一个对外提供接待访问者的接口。
关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。
应用实例:您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。
优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。
缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。
实现
类图
代码实现
public class Main {
public static void main(String[] args) {
EggRobot robot = new EggRobot();
//让机器人做计算
robot.calc();
//定义一个升级包
Visitor updatePack = new UpdateVisitor();
//要把这个升级包传给机器人
robot.accept(updatePack);
robot.calc();
}
//定义一个机器人
//注:这里static修饰只是因为在main函数里调用了相关函数,并无其它意义。
static class EggRobot {
//把硬件放入我们的机器人里面
private HardDisk disk;
private CPU cpu;
public EggRobot() {
disk = new HardDisk("记住 1+1=1");
cpu = new CPU("1+1=1");
}
//定义一个计算的方法
public void calc() {
cpu.run();
disk.run();
}
//机器人统一对外接收升级包,然后再分给各个硬件
public void accept(Visitor visitor) {
cpu.accept(visitor);
disk.accept(visitor);
}
}
//定义一个硬件的抽象类
//注:这里static修饰只是因为在main函数里调用了相关函数,并无其它意义。
abstract static class Hardware {
//它有自己的指令
String command;
public Hardware(String command) {
this.command = command;
}
//定义一个运行函数
public void run() {
System.out.println(command);
}
//它可以让我们的软件包进行访问,那么它一定能接受软件包的请求
//所以我们需要提供一个入口给软件包
//这里定义成抽象方法,让子类去实现
public abstract void accept(Visitor visitor);
}
//定义一个CPU
//注:这里static修饰只是因为在main函数里调用了相关函数,并无其它意义。
static class CPU extends Hardware {
public CPU(String command) {
super(command);
}
@Override
public void accept(Visitor visitor) {
//让这个访问器可以访问我这个CPU
visitor.visitCPU(this);
}
}
//定义一个磁盘
//注:这里static修饰只是因为在main函数里调用了相关函数,并无其它意义。
static class HardDisk extends Hardware {
public HardDisk(String command) {
super(command);
}
@Override
public void accept(Visitor visitor) {
//让这个访问器可以访问我这个Disk
visitor.visitDisk(this);
}
}
//定义一个软件包作为访问者
interface Visitor {
//定义一个接口方法,让visitor能够访问CPU
void visitCPU(CPU cpu);
////定义一个接口方法,让visitor能够访问磁盘
void visitDisk(HardDisk disk);
}
//定义一个软件包的具体的实现类
//注:这里static修饰只是因为在main函数里调用了相关函数,并无其它意义。
static class UpdateVisitor implements Visitor {
@Override
public void visitCPU(CPU cpu) {
//扩展指令,进行升级操作
cpu.command += ":1+1=2";
}
@Override
public void visitDisk(HardDisk disk) {
//扩展指令,进行升级操作
disk.command += "记住:1+1=2";
}
}
}
运行结果
1+1=1
记住 1+1=1
1+1=1:1+1=2
记住 1+1=1记住:1+1=2
此文章参考:
【菜鸟教程】:https://www.runoob.com/design-pattern/visitor-pattern.html
【五分钟学设计模式.23.访问者模式-哔哩哔哩】: https://b23.tv/U792UYp
标签:记录,visitor,void,模式,static,command,public,访问者 From: https://www.cnblogs.com/galo/p/17058737.html