我们使用了一个访问者类,它改变了元素类的执行算法
元素的执行算法可以随着访问者改变而改变
意图:主要将数据结构与数据操作分离。
菜鸟案例:
我们将创建一个定义接受操作的 ComputerPart 接口。Keyboard、Mouse、Monitor 和 Computer 是实现了 ComputerPart 接口的实体类。我们将定义另一个接口 ComputerPartVisitor,它定义了访问者类的操作。Computer 使用实体访问者来执行相应的动作。
VisitorPatternDemo,我们的演示类使用 Computer、ComputerPartVisitor 类来演示访问者模式的用法。
拆图
这里不是一个接口四个实现类这么简单,Computer 里面有一个ComputerPart 接口的数组,不用猜也知道是存它右边这三个实现类的,当然它有可能把自己也存进去了,可能性很高。
一个访问者的接口和访问者的实现了,连方法的参数都这么直白,就知道了,访问者可以访问Computer 所有的实现类
这直接说明,创建了一个ComputerPart的实体类Computer ,在构造方法里new出来了其他三个实体类加入到此对象的数组里,
创建了一个ComputerPartVisitor 的实体类ComputerPartDisplayVisitor当成参数传进Computer的 accept 方法,这有个误区,图上accept没有参数,但是实际中有参数
重点:传进去的参数对象会调用自身的visit() 访问此对象。
有点绕,就是ComputerPartVisitor.visit(this);,当然数组里的会遍历,到数组中的对象里的accept再调用ComputerPartVisitor.visit(this);
有点扯,但是它就是这么写的
上面的思路你可能有些混乱看下面的代码,建议从 (6) 顺着逻辑来,
直接看代码
(1)定义一个表示元素的接口
ComputerPart.java
public interface ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}
(2)创建扩展了上述类的实体类。
Keyboard.java
public class Keyboard implements ComputerPart {
//调用传过来的对象的visit
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
Monitor.java
public class Monitor implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
Mouse.java
public class Mouse implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
Computer.java
public class Computer implements ComputerPart {
ComputerPart[] parts;
public Computer(){
//在这构造方法里就new出来其他三个对象了并放进数组里
parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
}
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
for (int i = 0; i < parts.length; i++) {
//遍历,看有没有符合数组对象里的accept方法的,根据参数辨别
parts[i].accept(computerPartVisitor);
}
//最后直接让传过来的参数对象调用visit,参数为当前对象
computerPartVisitor.visit(this);
}
}
(3)定义一个表示访问者的接口。
ComputerPartVisitor.java
public interface ComputerPartVisitor {
public void visit(Computer computer);
public void visit(Mouse mouse);
public void visit(Keyboard keyboard);
public void visit(Monitor monitor);
}
(4)创建实现了上述类的实体访问者。
ComputerPartDisplayVisitor.java
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
//访问者重载的4个方法,这些是跟ComputerPart 的实体类相对应的
@Override
public void visit(Computer computer) {
System.out.println("Displaying Computer.");
}
@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}
@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}
@Override
public void visit(Monitor monitor) {
System.out.println("Displaying Monitor.");
}
}
(5)使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。
VisitorPatternDemo.java
public class VisitorPatternDemo {
public static void main(String[] args) {
//创建一个ComputerPart ,再往这个对象里的accept穿进去一个新的ComputerPartDisplayVisitor()
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
}
}
执行程序,输出结果:
Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.
最后这些结果还是ComputerPartDisplayVisitor 访问者的数据,而ComputerPart 只提供了一个操作的接口,通过操作ComputerPart 某个实体类来输出ComputerPartDisplayVisitor 里相对应的数据
————————————————
版权声明:本文为CSDN博主「胖墩的IT」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43113679/article/details/99590257