一、訪問者(Visitor)模式
訪問者模式的目的是封裝一些施加於某種數據結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的數據結構則可以保持不變。
問題提出
System.Collection命名空間下提供了大量集合操作對象。但大多數情況下處理的都是同類對象的聚集。換言之,在聚集上采取的操作都是一些針對同類型對象的同類操作。但是如果針對一個保存有不同類型對象的聚集采取某種操作該怎麼辦呢?
粗看上去,這似乎不是什麼難題。可是如果需要針對一個包含不同類型元素的聚集采取某種操作,而操作的細節根據元素的類型不同而有所不同時,就會出現必須對元素類型做類型判斷的條件轉移語句。這個時候,使用訪問者模式就是一個值得考慮的解決方案。
訪問者模式
訪問者模式適用於數據結構相對未定的系統,它把數據結構和作用於結構上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化。
數據結構的每一個節點都可以接受一個訪問者的調用,此節點向訪問者對象傳入節點對象,而訪問者對象則反過來執行節點對象的操作。這樣的過程叫做"雙重分派"。節點調用訪問者,將它自己傳入,訪問者則將某算法針對此節點執行。
雙重分派意味著施加於節點之上的操作是基於訪問者和節點本身的數據類型,而不僅僅是其中的一者。
二、訪問者模式的結構
如下圖所示,這個靜態圖顯示了有兩個具體訪問者和兩個具體節點的訪問者模式的設計,必須指出的是,具體訪問者的數目與具體節點的數目沒有任何關系,雖然在這個示意性的系統裡面兩者的數目都是兩個。
訪問者模式涉及到抽象訪問者角色、具體訪問者角色、抽象節點角色、具體節點角色、結構對象角色以及客戶端角色。
抽象訪問者(Visitor)角色:聲明了一個或者多個訪問操作,形成所有的具體元素角色必須實現的接口。
具體訪問者(ConcreteVisitor)角色:實現抽象訪問者角色所聲明的接口,也就是抽象訪問者所聲明的各個訪問操作。
抽象節點(Node)角色:聲明一個接受操作,接受一個訪問者對象作為一個參量。
具體節點(Node)角色:實現了抽象元素所規定的接受操作。
結構對象(ObIEctStructure)角色:有如下的一些責任,可以遍歷結構中的所有元素;如果需要,提供一個高層次的接口讓訪問者對象可以訪問每一個元素;如果需要,可以設計成一個復合對象或者一個聚集,如列(List)或集合(Set)。