行为型-访问者模式

概念

Vistor Pattern:提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

访问者模式是一种较为复杂的行为型设计模式,包含 访问者 和 被访问元素 两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。

在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为「对象结构」,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。

比如下面:访问者有财务部门FADepartment和 HR 部门HRDepartment,通过访问雇员Employee来查看雇员的工作情况。

img

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 访问者抽象类
class IVisitor {
visit(element) {};
}

// 元素类抽象类
class IElement {
accept(visitor) {};
}

// 具体访问者
class Cashier extends IVisitor {
visit(element) {
console.log(`【Goods】Title: ${element.title}, price: ${element.price}`);
}
}

// 具体元素类
class Goods extends IElement {

constructor(title, price) {
super()
this.title = title;
this.price = price;
}
accept(visitor) {
visitor.visit(this);
}
}

// 客户端
let pencil = new Goods('铅笔', 2.5);
let cashier = new Cashier();
pencil.accept(cashier); // 【Goods】Title: 铅笔, price: 2.5

优点

  • 符合 “开闭原则”:增加新的访问操作意味着增加一个新的具体访问者类,实现简单,无须修改源代码
  • 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类钟,类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问
  • 让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作

缺点

  • 增加新的元素类很困难:每增加一个新的元素类意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,违背 “开闭原则”
  • 破坏封装:要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问