访问者模式

  • 抽象访问者 Visitor,根据需要访问的元素,通过重载定义各自的访问方法,对调用方element是透明的:

    • visit(ConcreteElement1)
    • visit(ConcreteElement2)
      ...
    • visit(ConcreteElementN)
  • ConcreteVisitor

    • visit 定义了访问方法的逻辑,组织调用被访问元素Element的业务逻辑doSomething方法
  • 抽象元素 Element

    • doSomething 定义业务逻辑
    • accept(Visitor) 那些抽象访问者可以访问自己
  • ConcreteElement

    • 实现doSomething
    • 实现accept方法,一般调用visitor对应的访问方法visit

结论

  • 本质上就是element.accept开始驱动 -> visitor.visit -> element.doSomething,多了一层访问者。
  • 针对访问对象的不同,执行不同的展现操作。

优点

  1. 符合单一职责原则,visitor负责展现逻辑,element负责业务逻辑。
  2. 展现的扩展性,只需在visitor里增加应对新element子类的visit方法即可。

缺点

  1. visitor依赖了element的实现。
  2. 修改element的业务逻辑同时,visitor也要做相应改动,修改困难。

双分派

  • 这里涉及到一个重要的Java概念:静态绑定和动态绑定
ParentElement xxx = new ChildElement();
ParentVisitor zzz = new ChildVisitor();
// act的参数传的是zzz,zzz的表面类型是Parent,如果有2个重载方法,act(parent) 和 act(child),调用的是前者,哪怕zzz的实际类型是child,这是编译期决定的静态绑定。
// xxx的实际类型是child,所以调用的act是child的act,而不是parent的act,这是运行期决定的动态绑定。
xxx.act(zzz) 

引入到访问者模式

public class ChildElement implements Element {
  // 注意,虽然形参类型是parent,但实际调用visit方法是动态绑定,所以调用的还是childVisitor的visit方法
   public void accept(ParentVisitor visitor) {
    // 而且element调用accept方法本身就是动态绑定,所以访问者模式可以做到2个都是动态绑定。
    visitor.visit(this); 
    }
}

你可能感兴趣的:(访问者模式)