Adds a new operation to object without changing the object. 表示一个作用于某个对象中各个元素的操作。它可以使你不改变元素的前提下定义作用于这些元素的操作。

    在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。


    动机:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作「污染」这些对象的类,使用访问者模式将这些封装到类中。

    • 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
    • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作「污染」这些对象的类,也不希望在增加新操作时修改这些类。

    实现结构:

    使用 Visitor 必须定义两个层次:a. 接受操作的元素。 b. 操作元素的访问者。


    经典的 Case 包括编译原理之中的语义分析器。比如在 javac 的编译器中就用到了 visitor 模式来执行各类语法树的访问、遍历和优化。


    1. abstract class Visitor {
    2. visit(node: TextNode);
    3. visit(node: ImageNode);
    4. }
    5. class PrettifyVisitor extends Visitor {
    6. visit(node: TextNode);
    7. visit(node: ImageNode);
    8. }
    9. class CopyVisitor extends Visitor {
    10. visit(node: TextNode);
    11. visit(node: ImageNode);
    12. }
    13. class Node {}
    14. class TextNode extends Node {
    15. copy() {
    16. // do some main jobs
    17. // do extra jobs via visitor
    18. this.accept(new CopyVisitor());
    19. }
    20. accept(visitor) {
    21. visitor.visitTextNode(this);
    22. }
    23. }
    24. class ImageNode extends Node {
    25. pretty() {
    26. this.accept(new PrettifyVisitor());
    27. }
    28. accept(visitor) {
    29. visitor.visit(this);
    30. }
    31. }
    32. const image = new ImageNode();
    33. image.accept(new PrettifyVisitor());

    效果:

    • 使得更容易增加和修改操作。
    • 访问者集中相关的操作而「分离无关的操作」。
    • 这也会使得增加 ConcreteElement 类,比如上面的例子中,要增加新的 ShadowNode 类型就会比较麻烦,因为增加之后,所有的 Visitor 子类都需要更新对应的处理方式。
    • 当然也会存在:「状态累积」以及「破坏 Element 对象的封装性」的问题。