访问:有目的的社交方式!
说白了,访问者就是:每个人对于不同人问出的相同问题的不同回复
比如同样的问题:你有房子吗?
你对看上的相亲对象会说:有(当然也不排除会有低调的会有没有)
对于没有看上的相亲对象会说:没有(当然也不排除有嘚瑟的会说有)
房子是你的财产,是一个元素(Element)
相亲对象是你的访问者(Visitor)
这两者就构成了访问者模式所需要的全部内容了
你的财产有:房子,车子,公司,存款等等
相亲对象有:你看上的,你没看上的,摇摆不定的
对于不同相亲对象要访问你的不同财产时,他们得到的答案是不同的。
这样就对你的数据结构(财产)和对数据的操作进行了分离(不同的回复)
当然使用访问者模式需要你的数据结构相对稳定,这样不断添加操作,只需要增加一个访问者就可以,但是如果一旦数据结构发生略微的变化,就会对有所访问者的操作进行修改,比如说由于你的公司赚钱了,你新建了一个属于你自己的农场,这样你的财产中就多出了农场,对于所有的相亲对象来说,每一个都需要新添加一个访问农场的方法,这就是访问者模式的缺点,也充分说明了上述例子是不适合使用访问者模式的。
上面就是访问者模式的UML类图,其中Visit和Element我们都已经知道具体是什么了,另外两个client和ObjectStructure又是个什么?这个ObjectStructure其实就是Element的集合,用上面的例子来说就是你所有的具体财产,那个Client就是你相亲的地方。
下面来简单看看代码
Element部分public interface Property {
void accept(Visitor visitor);
}
public class House implements Property{
int mianji;
int worth;
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class Car implements Property{
int number;
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
Visitor部分
public interface Visitor {
void visit(Car car);
void visit(House house);
}
public class Like implements Visitor{
@Override
public void visit(Car car) {
System.out.println("I have "+car.number+" cars.");
}
@Override
public void visit(House house) {
System.out.println("I have a "+house.mianji+" square metre house.");
}
}
public class Unlike implements Visitor{
@Override
public void visit(Car car) {
System.out.println("I don't have a car.");
}
@Override
public void visit(House house) {
System.out.println("I have a jia zhi -1.000.000¥ house.");
}
}
ObjectStructure
import java.util.ArrayList;
import java.util.List;
public class MyProperty {
private List properties = new ArrayList<>();
public MyProperty(){
Car car = new Car();
car.number = 10;
House house = new House();
house.worth = 1000000;
house.mianji = 3000;
properties.add(car);
properties.add(house);
}
public void answerQuestions(Visitor visitor){
properties.forEach(property -> property.accept(visitor));
}
}
Client
public class BlindDatePlace {
public static void main(String[] args) {
MyProperty myProperty = new MyProperty();
System.out.println("visitor1:");
Visitor visitor1 = new Unlike();
myProperty.answerQuestions(visitor1);
System.out.println("====2 thousand year later!============");
System.out.println("visitor2:");
Visitor visitor2 = new Like();
myProperty.answerQuestions(visitor2);
}
}
访问者模式相对来说增加了代码的复杂度,一般情况下很少会用到访问者模式,但如果真的要用访问者模式,那就是真的需要访问者模式了(听君一席话,如听一席话!)
我在开发的过程中遇到过使用访问者模式的应用,就是在注解处理的时候遇到的JCTree,也就是抽象语法树(AST)。
我是因为需要使用JCTree,所以才了解了一下访问者模式,这个JCTree大致就是在代码编译之前,向代码里面自动添加代码片段,lombok的实现原理。
下面是我学习访问者模式的时候,看到三篇感觉尚可的文章
参考资料:
访问者模式一篇就够了 - 简书
访问者 - 廖雪峰的官方网站
设计模式-访问者模式的应用_快乐的小小程序猿-CSDN博客_访问者模式的应用实例



