淺析設計模式:訪問者模式(Visitor)

    訪問者模式被應用於解決這一類問題:

    數據結構中保存着許多元素,對這些元素的處理應該放在什麼地方?通常我們最常見的做法就是將這些處理直接放在表示數據結構的類中,當然在很多情況下這算是一種最簡單便捷的方式了,例如java集合中也有很多對元素操作的方法是放在集合類中的。但是,當需要經常增加一些處理時,我們就不難發現這種方式存在弊端,即每次增加處理,都需要修改表示數據結構的類,這顯然違背了“開閉原則”!

開閉原則:對擴展開放,對修改關閉,提倡在不修改已有類的前提下擴展新的功能。

    怎麼解決這類問題?將數據結構與處理分開不就好了!表示數據結構的類只需要提供對"訪問者"開放的接口(API),而對元素的處理則由訪問者負責,當需要新增一種對元素的處理方式時,只需要編寫新的表示訪問者的類即可,這樣就無需對錶示數據結構的類(原有的代碼)進行修改,又擴展出了新功能。


訪問者模式中的角色:

  • Visitor:表示訪問者的抽象類,用於聲明對數據結構中xxx元素訪問的visit(xxx)方法。
  • ConcreteVisitor:表示具體的訪問者,繼承Visitor並對其聲明的抽象方法提供具體實現。
  • Element:表示元素的抽象類,即訪問者實際要訪問的對象,Element角色需要對訪問者提供一個開放的接口,即accept方法,該方法的參數就是Visitor角色。
  • ConcreteElement:表示具體的元素,提供accept方法的實現。
  • ObjectStructure:負責處理Element元素的集合,即表示數據結構的類。

是的很抽象,我們來看下它們之間的類圖關係:



接下來動手實踐,我們來模擬這樣一個場景:

    有一片果園,果園裏已經挖好了大大小小的坑,假設大的坑用來種蘋果樹,小的坑用來種桔子樹。類比於上述觀察者模式中的 角色我們不難發現,大的坑和小的坑分別表示兩種具體的元素ConcreteElement,樹農表示訪問者(ConcreteVisitor),坑需要接受樹農的訪問,而果園就是容納這些坑的數據結構。

1、編寫訪問者的抽象類(Visitor):

    代表果農這一角色,聲明瞭對不同坑(Element)作不同處理的方法。


2、編寫具體的訪問者(ConcreteVisitor):

   對Visitor中的抽象方法提供具體實現。


3、編寫元素的抽象類(Element):

   本案例中的元素就是大大小小的坑,聲明一個抽象方法,表示接受樹農的訪問。


4、編寫具體的元素類(ConcreteElement):

  蘋果樹坑和桔子樹坑都實現accept方法,接受樹農訪問自己。


5、編寫表示數據結構的類(ObjectStructure):


6、最後編寫測試類:


    最後總結一下,訪問者模式就是用於將數據結構和對元素的處理分離開來,當需要對元素添加新的處理,只需要新增訪問者,在訪問者中提供新的處理方法,而不需要修改表示數據結構的類本身,這很好的滿足了"開閉原則"。

    但是有一點需要注意:新增訪問者容易,但是新增元素就很困難了!假設你要新增一個梨樹坑,你要怎麼做?你需要在Farmer類(Visitor)中新增一個方法plant(PearHole hole),並在其所有子類中提供具體實現。

Ending ...奮鬥

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