参考文献

访问者模式

  • 表示要对对象结构的元素执行的操作
  • Visitor允许您定义新操作,而无需更改其操作的元素的类

组件

  • Visitor: 这是一个接口或抽象类,用于声明所有类型的可访问类的访问操作.通常操作的名称是相同的,并且操作通过方法签名来区分:输入对象类型决定调用哪个方法.
  • ConcreteVisitor: 对于每种类型的访问者,必须实现在抽象访问者中声明的所有访问方法.每个访客将负责不同的操作.当定义一个新的访问者时,它必须被传递到对象结构.
  • Visitable : 是声明接受操作的抽象.这是访问者对象能够“访问”对象的入口点.集合中的每个对象都应该实现此抽象,以便能够被访问.
  • ConcreteVisitable: 这些类实现 Visitable 接口或类并定义接受操作.使用accept操作将访问者对象传递给该对象.
  • ObjectStructure: 这是一个包含所有可以访问的对象的类.它提供了一种迭代所有元素的机制.这个结构不一定是一个集合. 可以是复杂的结构,例如复合对象.

实现方式

  • 定义访问者接口(Visitor):声明访问不同类型元素的方法,每个方法对应一个具体元素的访问操作.

    1
    2
    3
    4
    interface Visitor {
    void visit(ElementA element);
    void visit(ElementB element);
    }
  • 定义具体访问者类(ConcreteVisitor):实现访问者接口,为每个具体元素提供具体的访问操作.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class ConcreteVisitor implements Visitor {
    @Override
    public void visit(ElementA element) {
    System.out.println("访问者正在处理元素A");
    }

    @Override
    public void visit(ElementB element) {
    System.out.println("访问者正在处理元素B");
    }
    }
  • 定义可访问接口(Visitable):声明接受访问者对象的方法(通常是 accept(Visitor visitor)),该方法会调用访问者对象对应类型的访问方法.

    1
    2
    3
    interface Visitable {
    void accept(Visitor visitor);
    }
  • 定义具体可访问类(ConcreteVisitable):实现可访问接口,实现具体元素的访问逻辑,并在 accept 方法中调用访问者的方法.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class ElementA implements Visitable {
    @Override
    public void accept(Visitor visitor) {
    visitor.visit(this);
    }

    public void operationA() {
    // 元素A的特定操作
    }
    }
  • 定义对象结构类(ObjectStructure):包含一组可访问对象的集合或其他数据结构,提供迭代所有元素的方法.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class ObjectStructure {
    private List<Visitable> elements = new ArrayList<>();

    public void addElement(Visitable element) {
    elements.add(element);
    }

    public void removeElement(Visitable element) {
    elements.remove(element);
    }

    public void accept(Visitor visitor) {
    for (Visitable element : elements) {
    element.accept(visitor);
    }
    }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class Main {
    public static void main(String[] args) {
    // 创建访问者对象
    Visitor visitor = new ConcreteVisitor();

    // 创建元素对象
    ElementA elementA = new ElementA();
    ElementB elementB = new ElementB();

    // 创建对象结构并添加元素
    ObjectStructure objectStructure = new ObjectStructure();
    objectStructure.addElement(elementA);
    objectStructure.addElement(elementB);

    // 对象结构接受访问者操作
    objectStructure.accept(visitor);
    }
    }

使用场景

  • 需要对一个复杂对象结构中的所有元素执行某些操作:访问者模式可以帮助我们遍历一个复杂的对象结构,而不需要在每个元素的类中定义相同的遍历方法.通过将具体的访问逻辑封装在访问者中,我们可以轻松地为对象结构中的每个元素添加新的处理操作.
  • 清理辅助行为的业务逻辑:有时候,一个对象结构中的元素可能会有一些与主要行为无关的辅助行为,例如日志记录、数据统计等.使用访问者模式,我们可以将这些辅助行为的代码从元素类中分离出来,并将其集中到一个或多个访问者中进行处理,以提高代码的清晰度和可维护性.
  • 某个行为仅在类层次结构中的一些类中有意义,而在其他类中没有意义:有时候,我们可能需要在一个类层次结构中的一些特定类上执行一个特定的操作,而在其他类上不需要执行.通过使用访问者模式,我们可以轻松地将这些操作封装为一个访问者,并仅在需要的类中实现具体的访问逻辑,而其他类则不受影响.