Adds a new operation to object without changing the object. 表示一个作用于某个对象中各个元素的操作。它可以使你不改变元素的前提下定义作用于这些元素的操作。
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
动机:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作「污染」这些对象的类,使用访问者模式将这些封装到类中。
- 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作「污染」这些对象的类,也不希望在增加新操作时修改这些类。
实现结构:
使用 Visitor 必须定义两个层次:a. 接受操作的元素。 b. 操作元素的访问者。
经典的 Case 包括编译原理之中的语义分析器。比如在 javac
的编译器中就用到了 visitor
模式来执行各类语法树的访问、遍历和优化。
abstract class Visitor {
visit(node: TextNode);
visit(node: ImageNode);
}
class PrettifyVisitor extends Visitor {
visit(node: TextNode);
visit(node: ImageNode);
}
class CopyVisitor extends Visitor {
visit(node: TextNode);
visit(node: ImageNode);
}
class Node {}
class TextNode extends Node {
copy() {
// do some main jobs
// do extra jobs via visitor
this.accept(new CopyVisitor());
}
accept(visitor) {
visitor.visitTextNode(this);
}
}
class ImageNode extends Node {
pretty() {
this.accept(new PrettifyVisitor());
}
accept(visitor) {
visitor.visit(this);
}
}
const image = new ImageNode();
image.accept(new PrettifyVisitor());
效果:
- 使得更容易增加和修改操作。
- 访问者集中相关的操作而「分离无关的操作」。
- 这也会使得增加
ConcreteElement
类,比如上面的例子中,要增加新的ShadowNode
类型就会比较麻烦,因为增加之后,所有的 Visitor 子类都需要更新对应的处理方式。 - 当然也会存在:「状态累积」以及「破坏 Element 对象的封装性」的问题。