JS設(shè)計(jì)模式之訪問者模式的用法詳解
定義和特點(diǎn)
訪問者模式是一種行為型設(shè)計(jì)模式,用于將算法與對(duì)象結(jié)構(gòu)分離。 該模式允許你定義新的操作(訪問者)而無需修改現(xiàn)有對(duì)象結(jié)構(gòu)(被訪問者)。 通過這種方式,你可以在不改變對(duì)象結(jié)構(gòu)的情況下添加新的操作。
參與者
在訪問者模式中,有兩個(gè)主要角色:被訪問者和訪問者。
- 被訪問者:一個(gè)具有一組**元素和方法(method)**的對(duì)象結(jié)構(gòu)。
- 訪問者:一個(gè)能夠?qū)@些元素執(zhí)行不同**操作(visit)**的對(duì)象。
- 被訪問者提供了**接受(accept)**訪問者的方法,以便訪問者能夠在需要時(shí)訪問元素。
使用流程
- 首定義訪問者接口,其中包含一組訪問方法,每個(gè)方法對(duì)應(yīng)一種操作。
- 在被訪問者接口中添加一個(gè)接受訪問者的方法accept,以便訪問者可以訪問被訪問者的元素。
- 被訪問者的具體實(shí)現(xiàn)類需要實(shí)現(xiàn)這個(gè)接收訪問者的方法,并**將自身作為參數(shù)(this)**傳遞給訪問者的具體訪問方法。
- 創(chuàng)建一個(gè)具體的訪問者對(duì)象v,并將其傳遞給被訪問者的接受方法,即accept(v)
- 被訪問者將根據(jù)傳遞的訪問者對(duì)象調(diào)用相應(yīng)的訪問方法,從而執(zhí)行特定的操作。 通過這種【改變新建不同結(jié)構(gòu)的訪問者,而不修改被訪問者】的方式,你可以在不改變被訪問者的結(jié)構(gòu)的情況下,為其添加新的操作。
通俗的理解
訪問者設(shè)計(jì)模式有兩個(gè)部分完成,在實(shí)現(xiàn)不同目標(biāo)的過程中保持其中一方(被訪問者)的結(jié)構(gòu)不變,只修改另外一方的結(jié)構(gòu)(訪問者)。 也就是犧牲一個(gè)保全另外一個(gè)。
作用
訪問者模式允許你將算法與對(duì)象結(jié)構(gòu)分離,并通過定義訪問者接口和被訪問者接口來實(shí)現(xiàn)多態(tài)性。 這種模式適用于需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的元素進(jìn)行不同操作的場(chǎng)景,同時(shí)又希望保持對(duì)象結(jié)構(gòu)的穩(wěn)定性。
舉例
// 被訪問者接口:點(diǎn)心店 interface Bakery { accept(visitor: CustomerVisitor): void; make(): string; makePlus(): string; } // 具體的被訪問者:圓點(diǎn)心店 class CirclePastry implements Bakery { // 被訪問者的接受方法 accept(visitor: CustomerVisitor): void { // 將自身作為參數(shù)(this)傳遞給訪問者的具體訪問方法 visitor?.visitCirclePastry(this); } make(): string { return "制作圓點(diǎn)心"; } makePlus(): string { return "制作精品圓點(diǎn)心"; } } // 具體的被訪問者:方點(diǎn)心店 class SquarePastry implements Bakery { accept(visitor: CustomerVisitor): void { visitor?.visitSquarePastry(this); } make(): string { return "制作方點(diǎn)心"; } makePlus(): string { return "制作精品方點(diǎn)心"; } } // 訪問者接口:顧客 interface CustomerVisitor { visitCirclePastry(pastry: CirclePastry): void; visitSquarePastry(pastry: SquarePastry): void; } // 具體的訪問者:點(diǎn)心愛好者 class PastryLover implements CustomerVisitor { visitCirclePastry(pastry: CirclePastry): void { console.log(`點(diǎn)心愛好者選擇了${pastry.make()}`); } visitSquarePastry(pastry: SquarePastry): void { console.log(`點(diǎn)心愛好者選擇了${pastry.make()}`); } } // 使用示例 const circlePastry: Bakery = new CirclePastry(); const squarePastry: Bakery = new SquarePastry(); const pastryLover: CustomerVisitor = new PastryLover(); circlePastry.accept(pastryLover); // 輸出:點(diǎn)心愛好者選擇了制作圓點(diǎn)心 squarePastry.accept(pastryLover); // 輸出:點(diǎn)心愛好者選擇了制作方點(diǎn)心 // 在保證被訪問者結(jié)構(gòu)的不變的前提下通過修改訪問者的結(jié)構(gòu)達(dá)到完成不同操作的目的 // 訪問者接口:高級(jí)顧客 interface CustomerVisitorPlus { visitCirclePastry(pastry: CirclePastry): void; visitSquarePastry(pastry: SquarePastry): void; } // 具體的訪問者:高級(jí)點(diǎn)心愛好者 class PastryLoverWithMoney implements CustomerVisitorPlus { visitCirclePastry(pastry: CirclePastry): void { console.log(`點(diǎn)心愛好者選擇了${pastry.makePlus()}`); } visitSquarePastry(pastry: SquarePastry): void { console.log(`點(diǎn)心愛好者選擇了${pastry.makePlus()}`); } } const pastryLoverWithMoney: PastryLoverWithMoney = new PastryLoverWithMoney(); circlePastry.accept(pastryLoverWithMoney); // 輸出:點(diǎn)心愛好者選擇了制作高級(jí)圓點(diǎn)心 squarePastry.accept(pastryLoverWithMoney); // 輸出:點(diǎn)心愛好者選擇了制作高級(jí)方點(diǎn)心 // 可以看出來circlePastry和squarePastry都被復(fù)用了
Babel插件中的使用
在 Babel 插件中修改 AST(抽象語(yǔ)法樹)時(shí),通常會(huì)使用訪問者模式。
- 定義訪問者:定義一個(gè)訪問者對(duì)象,該對(duì)象包含用于處理不同類型的 AST 節(jié)點(diǎn)的方法。每個(gè)方法對(duì)應(yīng)一種 AST 節(jié)點(diǎn)類型,該方法將被調(diào)用以訪問和處理相應(yīng)類型的節(jié)點(diǎn)。
- 遍歷和修改 AST:通過使用 Babel 提供的遍歷器(
@babel/traverse
),可以遍歷整個(gè) AST。在遍歷過程中,對(duì)于每個(gè)訪問到的節(jié)點(diǎn),將根據(jù)節(jié)點(diǎn)的類型調(diào)用相應(yīng)的訪問者方法。 - 修改 AST:在訪問者方法中,您可以對(duì) AST 進(jìn)行修改。這可以涉及更改節(jié)點(diǎn)屬性、替換節(jié)點(diǎn)、添加新節(jié)點(diǎn)等操作。通過修改 AST,插件可以實(shí)現(xiàn)源代碼的轉(zhuǎn)換和重寫。
應(yīng)用場(chǎng)景
- DOM 操作:在瀏覽器中,DOM(文檔對(duì)象模型)表示網(wǎng)頁(yè)的結(jié)構(gòu)和內(nèi)容。使用訪問者模式,您可以定義一個(gè)訪問者對(duì)象,該對(duì)象可以遍歷 DOM 樹的節(jié)點(diǎn),并執(zhí)行相應(yīng)的操作。例如,可以創(chuàng)建一個(gè)訪問者來查找特定類型的節(jié)點(diǎn)、修改節(jié)點(diǎn)屬性或樣式,或執(zhí)行其他與 DOM 相關(guān)的操作。
- 數(shù)據(jù)結(jié)構(gòu)操作:JavaScript 中有許多內(nèi)置的數(shù)據(jù)結(jié)構(gòu),如數(shù)組、集合、映射等。通過使用訪問者模式,您可以定義一個(gè)訪問者對(duì)象,來對(duì)這些數(shù)據(jù)結(jié)構(gòu)進(jìn)行遍歷和操作。例如,可以創(chuàng)建一個(gè)訪問者來計(jì)算數(shù)組中的總和、過濾符合特定條件的元素,或者將映射轉(zhuǎn)換為另一種形式。
- 編譯器和解析器:在編譯器和解析器中,訪問者模式經(jīng)常被用來處理抽象語(yǔ)法樹(AST)。通過定義訪問者對(duì)象,可以遍歷 AST 并執(zhí)行各種語(yǔ)義分析、優(yōu)化或代碼生成操作。這樣可以將復(fù)雜的編譯器邏輯分離到不同的訪問者方法中,使其更易于維護(hù)和擴(kuò)展。
- 事件處理:在瀏覽器中,事件處理是非常常見的任務(wù)。訪問者模式可以用于處理不同類型的事件,并執(zhí)行相應(yīng)的操作。例如,可以創(chuàng)建一個(gè)訪問者來處理鼠標(biāo)事件、鍵盤事件或其他用戶交互事件。
- 數(shù)據(jù)校驗(yàn)和驗(yàn)證:當(dāng)需要對(duì)數(shù)據(jù)進(jìn)行復(fù)雜的校驗(yàn)和驗(yàn)證時(shí),訪問者模式可以提供一種結(jié)構(gòu)化的方法。您可以定義一個(gè)訪問者對(duì)象,該對(duì)象遍歷數(shù)據(jù)結(jié)構(gòu)并執(zhí)行各種校驗(yàn)邏輯。這樣可以將校驗(yàn)邏輯從數(shù)據(jù)結(jié)構(gòu)中分離出來,使其更加可維護(hù)和可擴(kuò)展。
以上就是JS設(shè)計(jì)模式之訪問者模式的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于JS訪問者模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS實(shí)現(xiàn)換膚功能的方法實(shí)例詳解
這篇文章主要介紹了JS實(shí)現(xiàn)換膚功能的方法,結(jié)合實(shí)例形式分析了javascript針對(duì)頁(yè)面元素屬性與樣式動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-01-01JS 打印功能代碼可實(shí)現(xiàn)打印預(yù)覽、打印設(shè)置等
一個(gè)不錯(cuò)的JS 打印功能代碼,包括打印預(yù)覽、打印設(shè)置等,里面整合了很多知識(shí),是一個(gè)不錯(cuò)的學(xué)習(xí)案例2014-10-10微信小程序?qū)崿F(xiàn)活動(dòng)報(bào)名登記功能(實(shí)例代碼)
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)活動(dòng)報(bào)名登記,本篇將介紹使用微信小程序?qū)崿F(xiàn)發(fā)起一個(gè)活動(dòng)報(bào)名的設(shè)計(jì),以此為基礎(chǔ),我們可以掌握微信小程序表單的基本用法,進(jìn)而在諸如疫情信息登記、出入報(bào)備等場(chǎng)景中使用小程序進(jìn)行開發(fā),滿足相關(guān)的需求,需要的朋友可以參考下2022-09-09JavaScript代碼壓縮工具UglifyJS和Google Closure Compiler的基本用法
網(wǎng)上搜索了,目前主流的Js代碼壓縮工具主要有Uglify、YUI Compressor、Google Closure Compiler,簡(jiǎn)單試用了UglifyJS 和Google Closure Compiler 兩種工具的基本用法,需要的朋友可以參考下2020-04-04一個(gè)無限級(jí)XML綁定跨框架菜單(For IE)
一個(gè)無限級(jí)XML綁定跨框架菜單(For IE)...2007-01-01