访问者模式:把被操作的对象作为元素,可变可拓展的操作作为访问者。
可以说访问者中有很多操作,然后访问者访问元素,对该元素进行操作,不同的访问者有不同的操作。
案例
定义访问者接口
public interface UniversalVisitor {
void visitorMan(Man man);
void visitorWoMan(WoMan woMan);
}
定义元素接口
public interface Person {
void accept(UniversalVisitor universalVisitor);
}
元素具体实现类,包括男人和女人
public class Man implements Person {
@Override
public void accept(UniversalVisitor universalVisitor) {
universalVisitor.visitorMan(this);
}
}
public class WoMan implements Person {
@Override
public void accept(UniversalVisitor universalVisitor) {
universalVisitor.visitorWoMan(this);
}
}
访问者具体实现类,目前有开心和哭,当然也可以定义其他的比如说囧、丧等
public class HappyVisitor implements UniversalVisitor{
@Override
public void visitorMan(Man man) {
System.out.println("男人开心");
}
@Override
public void visitorWoMan(WoMan woMan) {
System.out.println("女人开心");
}
}
public class CryVisitor implements UniversalVisitor{
@Override
public void visitorMan(Man man) {
System.out.println("男人哭");
}
@Override
public void visitorWoMan(WoMan woMan) {
System.out.println("女人哭");
}
}
通过结构对象把元素进行集中、然后统一进行访问
public class ObjectStructure {
private List<Person> elements = new ArrayList<>();
//增加
public void attach(Person person) {
elements.add(person);
}
//移除
public void detach(Person person) {
elements.remove(person);
}
//查看显示
public void display(UniversalVisitor universalVisitor) {
for (Person person : elements) {
person.accept(universalVisitor);
}
}
}
客户端
public class Client {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Man());
objectStructure.attach(new WoMan());
HappyVisitor happyVisitor = new HappyVisitor();
objectStructure.display(happyVisitor);
CryVisitor cryVisitor = new CryVisitor();
objectStructure.display(cryVisitor);
}
}
输出结果
男人开心
女人开心
男人哭
女人哭
结论
对于元素而言,不同的访问者就能进行不同的操作,我们只需要增加不同的访问者就可以了。
优缺点
优点:
符合单一职责原则
优秀的扩展性
灵活性非常高
缺点:
具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的
具体元素变更比较困难
违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素
源码分析
在 Spring IoC 中,BeanDefinition 用来存储 Spring Bean 的定义信息,比如属性值、构造方法参数或者更具体的实现。Spring 解析完配置后,会生成 BeanDefinition 并且记录下来。下次 getBean 获取 Bean 时,会通过 BeanDefinition 来实例化具体的 Bean 对象。
BeanDefinition 是一个接口,即一个抽象的定义,实际使用的是其实现类,如 ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition 等。
Spring 中的 BeanDefinitionVisitor 类主要用于访问 BeanDefinition,解析属性或者构造方法里面的占位符,并把解析结果更新到 BeanDefinition 中。这里应用的就是访问者模式。抽象元素为 BeanDefinition,具体元素有 RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition 等。
因为没有对访问者进行扩展,所以这里只有一个具体访问者 BeanDefinitionVisitor,没有再抽出一层抽象访问者。
参考博客:http://c.biancheng.net/view/8502.html
https://blog.csdn.net/qq_36970993/article/details/112760013?utm_term=JDK%E6%BA%90%E7%A0%81%20%E8%AE%BF%E9%97%AE%E8%80%85%E6%A8%A1%E5%BC%8F&utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2allsobaiduweb~default-1-112760013&spm=3001.4430