訪問者模式的定義 定義: 封裝一些作用於某種數據結構中的各元素的操作, 它可以在不改變數據結構的前提下定義作用於這些元素的新的操作 通俗的說, 就是定義一個訪問者角色, 當對指定角色進行訪問時要通過訪問者進行訪問 其類圖如下: 各角色說明: 抽象元素代碼: 具體元素代碼: 抽象訪問者代碼: 具體訪問 ...
訪問者模式的定義
定義: 封裝一些作用於某種數據結構中的各元素的操作, 它可以在不改變數據結構的前提下定義作用於這些元素的新的操作
通俗的說, 就是定義一個訪問者角色, 當對指定角色進行訪問時要通過訪問者進行訪問
其類圖如下:
各角色說明:
- Vistor 抽象訪問者: 抽象類或介面, 聲明訪問者可以訪問哪些元素, 具體到程式中就是 visit 方法的參數定義哪些對象是可以被訪問的
- ConcreteVistor 具體訪問者: 它影響訪問者訪問到一個類後該怎麼乾, 要做什麼事
- Element 抽象元素: 介面或抽象類, 聲明接受哪一類訪問者訪問, 程式上是通過 accept 方法中的參數來定義的
- ConcreteElement 具體元素: 實現 accept方法, 通常是 visitor.visit(this); 基本上都形成一種模式了
- ObjectStruture 結構對象: 元素的生成者, 一般容納在多個不同類、不同介面的容器, 項目中一般很少抽象出這個角色
抽象元素代碼:
具體元素代碼:
抽象訪問者代碼:
具體訪問者代碼:
結構對象用來產生不同的元素對象, 代碼如下:
場景類代碼:
通過增加訪問者, 這要是具體元素就非常容易訪問, 對元素的遍歷就更加容易了, 甭管它是什麼對象, 只要它在一個容器中, 都可以通過訪問者來訪問, 任務集中化.
訪問者模式的應用
訪問者模式的優點:
- 符合單一職責原則. 具體元素角色負責數據的載入, 而訪問者角色負責報表的展現, 兩個不同的職責非常明確的分離開來, 各自演繹變化
- 優秀的擴展. 由於職責分開,繼續增加 對數據的操作是非常快捷的.
- 靈活性非常高. 例如, 當需要對不同的具體元素進行分別統計時, 使用 instanceof 迴圈判斷當然也可以, 但是現在有一個好辦法, 那就是把它丟給訪問者,由訪問者來進行統計計算
訪問者模式的缺點:
- 具體元素對訪問者公佈細節. 訪問者要訪問一個類就必然要求這個類公佈一些方法和數據, 也就是說訪問者關註了其他類的內部細節, 這也是迪米特法則所不建議的
- 具體元素變更比較困難. 具體元素角色的增加、刪除、修改是比較困難的
- 違背了依賴倒置原則. 訪問者依賴的是具體元素, 而不是抽象元素, 這破壞了依賴倒置原則, 特別是在面向對象的編程中, 拋棄了對 介面的依賴,而直接依賴實現類, 擴展比較難
訪問者模式的應用場景:
- 一個對象結構包含很多類對象, 它們有不同的介面, 而你想對這些對象實施一些依賴於其具體類的操作, 也就是說用迭代器模式已經不能勝任的情景
- 需要對一個對象結構中的對象進行很多不同並且不相關的操作, 而你想避免讓這些操作"污染"這些對象的類
- 業務規則要求遍歷多個不同的對象. 這本身也是訪問者模式的出發點, 訪問者模式是對迭代器模式的擴充, 可以便利不同的對象, 然後執行不同的操作, 也就是針對訪問的對象不同,執行不同的操作.
- 訪問者模式還有一個 用途, 充當攔截器角色
訪問者模式的擴展
1.統計功能
對不同的具體元素進行統計, 針對不同的具體元素針對性統計
比如統計員工工資, 經理和員工的工資情況不同, 使用訪問者進行分別計算, 然後可以計算總額等
2.多個訪問者
可以定義多個訪問者, 每個訪問者實現不同的功能
在IVistor 下再定義 介面繼承 IVistor, 分別實現各自功能, 使用時傳遞不同的訪問者有不同的表現
訪問者模式是一種集中規整模式,特別使用於大規模重構的項目, 在這一個階段需求已經非常清晰, 原系統的功能點也已經明確, 通過訪問者模式可以很容易把一些功能進行梳理, 達到最終目的--功能集中化, 如一個統一的報表運算、UI展現等, 我們還可以與其它模式混編建立一套自己的過濾器或者攔截器