為什么要用訪問(wèn)者模式:在OOP中,我們用類來(lái)組織代碼,類的屬性我們當(dāng)然在類內(nèi)部獲取,方法也在內(nèi)部實(shí)現(xiàn),使用就new一個(gè)類調(diào)用方法,但是當(dāng)我們需要對(duì)類的數(shù)據(jù)進(jìn)行很多與類定義不相關(guān)的操作的時(shí)候,這個(gè)時(shí)候我們又不想污染類的對(duì)象,因?yàn)檫@些操作引起的副作用可能根本與類無(wú)關(guān),那么我們就應(yīng)該把這些操作抽離出來(lái)單獨(dú)封裝,但是你抽離出來(lái)還是要用類的數(shù)據(jù)呀,怎么辦呢,好了,所有類實(shí)現(xiàn)一個(gè)訪問(wèn)的接口,接受訪問(wèn)者,內(nèi)部調(diào)用訪問(wèn)者的行為,但是具體這些行為干了什么,是訪問(wèn)者在外面實(shí)現(xiàn)的,就好像你作為一個(gè)訪問(wèn)者去拜訪朋友家,朋友說(shuō)你可以在我家做飯,用我家東西,但是具體怎么做是你的事,你朋友家并不關(guān)心,這樣,換朋友來(lái)訪問(wèn),同樣也可以讓他們做飯,但是做飯的方式就不一樣了撒
訪問(wèn)者的目的: 主要將穩(wěn)定的數(shù)據(jù)結(jié)構(gòu)和易變的操作分開(kāi),方便擴(kuò)展多變的操作方法而保持穩(wěn)定的數(shù)據(jù)結(jié)構(gòu)
訪問(wèn)者的實(shí)現(xiàn): talk is cheap, show you the code
// 定義獎(jiǎng)金的訪問(wèn)者,在js中簡(jiǎn)單的用一個(gè)函數(shù)模擬,
// 如果在c#等強(qiáng)類型語(yǔ)言中,需要聲明一個(gè)接口,不同的visitor實(shí)現(xiàn)不同的計(jì)算獎(jiǎng)金方法,
// 比如下面的管理者和開(kāi)發(fā)者獎(jiǎng)金不一樣
function bonusVisitor(employee) {
if (employee instanceof Manager)
employee.bonus = employee.salary * 2;
if (employee instanceof Developer)
employee.bonus = employee.salary;
}
// 定義員工類,注意繼承此類的必須都帶有accept這個(gè)接受visitor的方法,
// 就是用來(lái)接待訪問(wèn)者,進(jìn)而內(nèi)部用訪問(wèn)者調(diào)用自己方法實(shí)現(xiàn)一些操作,
// 此例中直接調(diào)用函數(shù)visitor(this)
class Employee {
constructor(salary) {
this.bonus = 0;
this.salary = salary;
}
accept(visitor) {
visitor(this);
}
}
// 管理者實(shí)現(xiàn)員工類
class Manager extends Employee {
constructor(salary) {
super(salary);
}
}
// 開(kāi)發(fā)者實(shí)現(xiàn)員工類
class Developer extends Employee {
constructor(salary) {
super(salary);
}
}
測(cè)試代碼
// 管理員工集合
let employees = [];
// 不同的員工
const john = new Developer(4000);
const christian = new Manager(10000);
// 放入員工集合中
employees.push(john);
employees.push(christian);
// 分別接收訪問(wèn)者并調(diào)用
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