为什么要用访问者模式:在OOP中,我们用类来组织代码,类的属性我们当然在类内部获取,方法也在内部实现,使用就new一个类调用方法,但是当我们需要对类的数据进行很多与类定义不相关的操作的时候,这个时候我们又不想污染类的对象,因为这些操作引起的副作用可能根本与类无关,那么我们就应该把这些操作抽离出来单独封装,但是你抽离出来还是要用类的数据呀,怎么办呢,好了,所有类实现一个访问的接口,接受访问者,内部调用访问者的行为,但是具体这些行为干了什么,是访问者在外面实现的,就好像你作为一个访问者去拜访朋友家,朋友说你可以在我家做饭,用我家东西,但是具体怎么做是你的事,你朋友家并不关心,这样,换朋友来访问,同样也可以让他们做饭,但是做饭的方式就不一样了撒
访问者的目的: 主要将稳定的数据结构和易变的操作分开,方便扩展多变的操作方法而保持稳定的数据结构
访问者的实现: talk is cheap, show you the code
// 定义奖金的访问者,在js中简单的用一个函数模拟,
// 如果在c#等强类型语言中,需要声明一个接口,不同的visitor实现不同的计算奖金方法,
// 比如下面的管理者和开发者奖金不一样
function bonusVisitor(employee) {
if (employee instanceof Manager)
employee.bonus = employee.salary * 2;
if (employee instanceof Developer)
employee.bonus = employee.salary;
}
// 定义员工类,注意继承此类的必须都带有accept这个接受visitor的方法,
// 就是用来接待访问者,进而内部用访问者调用自己方法实现一些操作,
// 此例中直接调用函数visitor(this)
class Employee {
constructor(salary) {
this.bonus = 0;
this.salary = salary;
}
accept(visitor) {
visitor(this);
}
}
// 管理者实现员工类
class Manager extends Employee {
constructor(salary) {
super(salary);
}
}
// 开发者实现员工类
class Developer extends Employee {
constructor(salary) {
super(salary);
}
}
测试代码
// 管理员工集合
let employees = [];
// 不同的员工
const john = new Developer(4000);
const christian = new Manager(10000);
// 放入员工集合中
employees.push(john);
employees.push(christian);
// 分别接收访问者并调用
employees.forEach(e => {
e.accept(bonusVisitor);
});
参考:
https://www.runoob.com/design-pattern/visitor-pattern.html
https://cnblogs.com/Terrylee/archive/2006/07/17/334911.html