訪問者模式(Visitor Pattern)的c++實現示例

訪問者模式是一種分離對象數據結構與行爲的方法,通過這種分離,可以爲一個已存在的類或類羣(即被訪問者)增加新的操作(即訪問者)而無需爲它們作任何修改。訪問者模式屬於行爲型模式。

 

爲什麼要使用訪問者模式?
    如何擴展一個現有的類層次結構來實現新行爲?一般的方法是給類添加新的方法。但是萬一新行爲和現有對象模型不兼容怎麼辦?還有,類層次結構設計人員可能無法預知以後開發過程中將會需要哪些功能。以及,如果已有的類層次結構不允許修改代碼,怎麼能擴展行爲呢?
    答案是在類層次結構設計中使用訪問者模式。

 

訪問者模式涉及的角色:
1)訪問者(Visitor)
    訪問者抽象接口,通過visit(Element)方法訪問Element(數據結構),完成對Element的操作行爲。
2)具體訪問者(ConcreteVisitor)
    訪問者的具體實現類。
3)元素(Element),也就是被訪問者
    通過accept(Visitor)方法接受Visitor的訪問。
4)具體元素(ConcreteElement)
    元素的具體實現類。
5)對象結構(ObjectStructure)
    擁有一組元素的組合對象。ObjectStructure本身也可以作爲被訪問者。

 

訪問者模式的結構圖(網上下載的):

訪問者模式結構圖(uml圖)

當一個應用滿足以下條件時,我們可以使用Visitor設計模式:
1)一個對象結構包含很多類對象,它們有不同的接口,而你想對這些對象實施一些依賴於其具體類的操作。
2)需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而你想避免讓這些操作“污染”這些對象的類。Visitor使得你可以將相關的操作集中起來定義在一個類中。
3) 當該對象結構被很多應用共享時,用Visitor模式讓每個應用僅包含需要用到的操作。
4) 定義對象結構的類很少改變,但經常需要在此結構上定義新的操作。改變對象結構類需要重定義對所有訪問者的接口,這可能需要很大的代價。如果對象結構類經常改變,那麼可能還是在這些類中定義這些操作較好。

 

優點:
1)易於添加那些目前尚未考慮到的方法。(這也是使用訪問者的原因:擴展功能)
2)可以使類更加小巧,因爲那些很少使用的方法,可以在外部定義。(意味着如果一個方法經常使用,最好定義在類中;當然在第一次定義中沒有考慮到此方法除外)

 

缺點:
1)訪問者角色不適合具體元素角色經常發生變化的情況。(如:增加新具體元素類,訪問者接口就需要改變了。)
2)訪問者角色要執行與元素角色相關的操作,就必須讓元素角色將自己內部屬性暴露出來,這就破壞了元素角色的封裝性。訪問者和被訪問的對象的耦合性很大。
3)元素與訪問者之間能夠傳遞的信息有限,這往往也會限制訪問者模式的使用。(因爲訪問者不能直接訪問元素的私有數據)

 

示例:

 

後話:
   使用了訪問者模式以後,對於原來的類層次增加新的操作,僅僅需要實現一個具體訪問者角色就可以了,而不必修改整個類層次。而且這樣符合“開閉原則”的要求。而且每個具體的訪問者角色都對應於一個相關操作,因此如果一個操作的需求有變,那麼僅僅修改一個具體訪問者角色,而不用改動整個類層次。但是“開閉原則”的遵循總是片面的。如果系統中的類層次發生了變化,會對訪問者模式產生什麼樣的影響呢?你必須修改訪問者角色和每一個具體訪問者角色。
   模式設計教材書經常提及的一句話:發現變化並封裝之。是否採用訪問者模式,就要看(或預見)“變化”是什麼了。訪問者模式中,“變化”是主要是具體訪問者,其次是對象結構。但如果(具體)元素也改變,就萬萬不能用訪問者模式,因爲“牽一髮動全身”,維護性就太差了。
   再嘮叨一下爲什麼使用訪問者模式的個人看法:
對象結構使用的了(具體)元素(即被訪問者),而(具體)元素的功能不全,而直接在元素中添加功能不太好(如:不允許修改元素;或者增加不常用的功能會使類太臃腫等等),那麼我們就定一個輔助類(就是訪問者)來完成這個功能。於是,作爲預見性,我們爲元素(即被訪問者)增加一個accept(Visitor)方法作爲接口,以作不時之需。爲元素增加新的功能,只需增加新的訪問者類。


參考文獻:
1.《設計模式初學者指南》,徐迎曉等譯,機械工業出版社
2.網上,東抄一下,西抄一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章