访问者模式
● Visitor——抽象访问者
抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法的参数定
义哪些对象是可以被访问的。
● ConcreteVisitor——具体访问者
它影响访问者访问到一个类后该怎么干,要做什么事情。
● Element——抽象元素
接口或者抽象类,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定
义的。
● ConcreteElement——具体元素
实现accept方法,通常是visitor.visit(this),基本上都形成了一种模式了。
● ObjectStruture——结构对象
元素产生者,一般容纳在多个不同类、不同接口的容器,如List、Set、Map等,在项目
中,一般很少抽象出这个角色。
抽象元素
public abstract class Element {
//定义业务逻辑
public abstract void doSomething();
//允许谁来访问
public abstract void accept(IVisitor visitor);
}
抽象元素有两类方法:一是本身的业务逻辑,也就是元素作为一个业务处理单元必须完
成的职责;另外一个是允许哪一个访问者来访问。
具体元素
public class ConcreteElement1 extends Element{
//完善业务逻辑
public void doSomething(){
//业务处理
}
//允许那个访问者访问
public void accept(IVisitor visitor){
visitor.visit(this);
}
}
public class ConcreteElement2 extends Element{
//完善业务逻辑
public void doSomething(){
//业务处理
}
//允许那个访问者访问
public void accept(IVisitor visitor){
visitor.visit(this);
}
}
它定义了两个具体元素,我们再来看抽象访问者,一般是有几个具体元素就有几个访问
方法
抽象访问者
public interface IVisitor {
//可以访问哪些对象
public void visit(ConcreteElement1 el1);
public void visit(ConcreteElement2 el2);
}
具体访问者
public class Visitor implements IVisitor {
//访问el1元素
public void visit(ConcreteElement1 el1) {
el1.doSomething();
}
//访问el2元素
public void visit(ConcreteElement2 el2) {
el2.doSomething();
}
}
结构对象是产生出不同的元素对象
结构对象
public class ObjectStruture {
//对象生成器,这里通过一个工厂方法模式模拟
public static Element createElement(){
Random rand = new Random();
if(rand.nextInt(100) > 50){
return new ConcreteElement1();
}else{
return new ConcreteElement2();
}
}
}
场景类
public class Client {
public static void main(String[] args) {
for(int i=0;i<10;i++){
//获得元素对象
HuDun Demo
Element el = ObjectStruture.createElement();
//接受访问者访问
el.accept(new Visitor());
}
}
}
通过增加访问者,只要是具体元素就非常容易访问,对元素的遍历就更加容易了,甭管
它是什么对象,只要它在一个容器中,都可以通过访问者来访问,任务集中化。这就是访问
者模式。
访问者模式的优点
● 符合单一职责原则
具体元素角色也就是Employee抽象类的两个子类负责数据的加载,而Visitor类则负责报
表的展现,两个不同的职责非常明确地分离开来,各自演绎变化。
● 优秀的扩展性
由于职责分开,继续增加对数据的操作是非常快捷的
● 灵活性非常高
访问者模式的缺点
● 具体元素对访问者公布细节
访问者要访问一个类就必然要求这个类公布一些方法和数据,也就是说访问者关注了其
他类的内部细节,这是迪米特法则所不建议的。
● 具体元素变更比较困难
具体元素角色的增加、删除、修改都是比较困难的
● 违背了依赖倒置转原则
访问者依赖的是具体元素,而不是抽象元素,这破坏了依赖倒置原则,特别是在面向对
象的编程中,抛弃了对接口的依赖,而直接依赖实现类,扩展比较难。
访问者模式的使用场景
● 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖
于其具体类的操作,也就说是用迭代器模式已经不能胜任的情景。
● 需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操
作“污染”这些对象的类。
访问者模式还有一个用途,就是充当拦截器(Interceptor)角色