Java設計模式--訪問者模式

訪問者模式【Visitor Pattern 】

以打印公司員工的信息報表爲例。下面先看下類圖。

這裏寫圖片描述

使用了一個模版方法模式,把所要的信息都打印出來。這樣子寫出來的代碼就不太符合公司不同管理層的需要,不能滿足各自的需求。

每個普通員工類和經理類都一個方法 report,那是否可以把這個方法提取到另外一個類中來實現呢。最初的類圖如下:

這裏寫圖片描述

兩個類中都有report()方法,那麼再進行一些改善。

這裏寫圖片描述

這樣子就將report()方法提煉出來了,再看下下面這個。

這裏寫圖片描述

在抽象類 Employee 中增加了 accept 方法,這個方法是定義我這個類可以允許被誰來訪問,也就定義一類訪問者,在具體的實現類中調用訪問者的方法。

那在具體類中就可以設置訪問者了。

public void accept(IVisitor visitor){
visitor.visit(this);
}

在主類進行調用時直接傳入訪問者進行訪問公司不同角色的信息。

for(Employee emp:mockEmployee()){
    emp.accept(new Visitor());
}

再看一下他的通用類圖:

這裏寫圖片描述

來看一下這幾個角色的職責:
抽象訪問者(Visitor) :抽象類或者接口,聲明訪問者可以訪問哪些元素,具體到程序中就是 visit方法的參數定義哪些對象是可以被訪問的;

具體訪問者(ConcreteVisitor):訪問者訪問到一個類後該怎麼幹(哎,這個別讀歪了),要做什麼事情;

抽象元素(Element) :接口或者抽象類,聲明接受那一類型的訪問者訪問,程序上是通過 accept 方法中的參數來定義;

具體元素: (ConcreteElement):實現 accept 方法,通常是 visitor.visit(this),基本上都形成了一個套路了;

結構對象(ObjectStruture):容納多個不同類、不同接口的容器,比如 List、Set、Map 等,在項目中,一般很少抽象出來這個角色;

總結:
應用場景:
先與迭代器模式比較一下,迭代器模式只能訪問同類或同接口的數據, (當然了,你使用 instanceof 的話,能訪問所有的數據,這個不爭論) ,而訪問者模式是對迭代器模式的擴充,可以遍歷不同的對象,然後執行不同的操作,也就是針對訪問的對象不同,執行不同的操作。故可以將訪問者模式應用到遍歷不同的對象,然後執行不同的操作的項目當中。比如統計(統計公司人員的工資等)、有多個訪問者的情況(上述的訪問者其實可以再進行細分,一個用於展示報表的信息,一個用於計算報表中的一些信息)、充當攔截器(以後進行補充)。

優點
(1)符合單一職責原則,具體元素角色也就是Employee 這個類的兩個子類負責數據的加載,而Visitor 類則負責報表的展現,兩個不同的職責非常明確的分離開來,各自演繹而變化。

(2)由於職責分開,繼續增加對數據的操作是非常快捷的。擴展性良好。

缺點:
(1)訪問者要訪問一個類就必然要求這個類公佈一些方法,也就是說訪問者關注了其他類的內部細節,這是迪米特法則所不建議的;

(2)具體角色的增加刪除修改都是比較苦難的,就上面那個例子,你想想,你要是想增加一個成員變量,比如年齡 age,Visitor 就需要修改,如果 Visitor 是一個還好說,多個呢?業務邏輯再複雜點呢。

發佈了46 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章