文章首發: "行為型模式:訪問者模式" 十一大行為型模式之十一:訪問者模式。 簡介 姓名 :訪問者模式 英文名 :Visitor Pattern 價值觀 :來訪者便是客,招待就是 個人介紹 : Represent an operation to be performed on the element ...
文章首發:
行為型模式:訪問者模式
十一大行為型模式之十一:訪問者模式。
簡介
姓名 :訪問者模式
英文名 :Visitor Pattern
價值觀 :來訪者便是客,招待就是
個人介紹 :
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
封裝一些作用於某種數據結構中的各元素的操作,它可以在不改變數據結構的前提下定義作用於這些元素的新的操作。
(來自《設計模式之禪》)
你要的故事
先聲明一下,下麵故事全瞎編的。。。
我們是否還記得 N 年前反腐開始的時候,有一段時間提倡官員宴請吃飯只能幾菜幾湯,不能超出。我記得那會剛讀大一,軍事理論的老師說到這個問題,也發表了他的一些想法,他覺得這麼做比較刻板。今天的故事就和宴請有關。現在中國企業發展越來越大,在社會中擔任的責任也越來越大,政府也越來越重視企業,官員去參觀企業是常有的事,而企業宴請官員也變得格外的常見。
故事的背景就是企業宴請各級官員。不同級別的官員宴請的菜式就不一樣,每家企業的菜式豐富程度也不一樣。我們這裡的訪問對象就用 Alibaba 和 Tencent 這 2 家公司,而訪問者就用郭嘉領導人和省領導人做舉例。這 2 家公司都跟喜來登酒店合作,Alibaba 合作方案是:宴請省領導人則十菜一湯,宴請郭嘉領導人則十四菜兩湯;Tencent 合作方案是:宴請省領導人則八菜一湯,宴請郭嘉領導人則十六菜兩湯。
下麵看看如何用訪問者模式來實現上面的故事。
首先定義一個抽象類:企業。企業有一個共有的特性就是接受上級領導的訪問。
/**
* 企業
*/
abstract class Company {
public abstract void accept(Vistor vistor);
}
上面故事我們舉例了 2 家企業,分別是 Alibaba 和 Tencent,這裡實現這 2 家公司的宴請方案,並實現接待訪問者方法。
Alibaba 宴請郭嘉領導人是十四菜兩湯,宴請省領導是十菜一湯。
/**
* Alibaba 企業
*/
class AlibabaCompany extends Company {
@Override
public void accept(Vistor vistor) {
vistor.visit(this);
}
public String entertainProvincialLeader() {
return "Alibaba 接待省領導:十菜一湯";
}
public String entertainNationalLeader() {
return "Alibaba 接待郭嘉領導:十四菜兩湯";
}
}
Tencent 宴請郭嘉領導人是十六菜兩湯,宴請省領導是八菜一湯。
/**
* Tencent 企業
*/
class TencentCompany extends Company {
@Override
public void accept(Vistor vistor) {
vistor.visit(this);
}
public String entertainProvincialLeader() {
return "Tencent 接待省領導:八菜一湯";
}
public String entertainNationalLeader() {
return "Tencent 接待郭嘉領導:十六菜兩湯";
}
}
這裡定義訪問者介面,訪問者介面有 2 個方法,分別是訪問 Alibaba 企業和訪問 Tencent 企業。
/**
* 訪問者介面
*/
interface Vistor {
void visit(AlibabaCompany alibabaCompany);
void visit(TencentCompany tencentCompany);
}
上面故事中有 2 個訪問者,一個是郭嘉領導人,另一個是省領導人,因為不同企業對應不同訪問者有不同的宴請方案,所以這裡訪問企業是需要調用對應企業的宴請方式。
省領導人訪問企業時,需要調用企業對省領導人的宴請方案,為entertainProvincialLeader()
/**
* 省領導訪問
*/
class ProvincialLeaderVistor implements Vistor {
@Override
public void visit(AlibabaCompany alibabaCompany) {
System.out.println(alibabaCompany.entertainProvincialLeader());
}
@Override
public void visit(TencentCompany tencentCompany) {
System.out.println(tencentCompany.entertainProvincialLeader());
}
}
郭嘉領導人訪問企業時,需要調用企業對郭嘉領導人的宴請方案,為entertainNationalLeader()
/**
* 郭嘉領導訪問
*/
class NationalLeaderVistor implements Vistor {
@Override
public void visit(AlibabaCompany alibabaCompany) {
System.out.println(alibabaCompany.entertainNationalLeader());
}
@Override
public void visit(TencentCompany tencentCompany) {
System.out.println(tencentCompany.entertainNationalLeader());
}
}
上面是訪問者和被訪問者的代碼,因為企業是在喜來登酒店宴請領導人,所以這裡還需要一個酒店,酒店裡面有企業合作的名單,以及負責宴請各路領導的方法提供。
/**
* 酒店
*/
class Hotel {
private List<Company> companies = new ArrayList<>();
public void entertain(Vistor vistor) {
for (Company company : companies) {
company.accept(vistor);
}
}
public void add(Company company) {
companies.add(company);
}
}
下麵提供測試代碼,看看運行的結果怎樣。
public class VisitorTest {
public static void main(String[] args) {
AlibabaCompany alibabaCompany = new AlibabaCompany();
TencentCompany tencentCompany = new TencentCompany();
ProvincialLeaderVistor provincialLeaderVistor = new ProvincialLeaderVistor();
NationalLeaderVistor nationalLeaderVistor = new NationalLeaderVistor();
Hotel xilaideng = new Hotel();
xilaideng.add(alibabaCompany);
xilaideng.add(tencentCompany);
xilaideng.entertain(provincialLeaderVistor);
xilaideng.entertain(nationalLeaderVistor);
}
}
列印結果:
Alibaba 接待省領導:十菜一湯
Tencent 接待省領導:八菜一湯
Alibaba 接待郭嘉領導:十四菜兩湯
Tencent 接待郭嘉領導:十六菜兩湯
完整的訪問者模式代碼已經呈現,花 1 分鐘思考一番,理解整個代碼後我們來看看下麵的總結。
總結
訪問者模式有比較好的擴展性,看看訪問者代碼,我們如果要新增一個訪問者:市領導人,只需新增市領導人類,然後企業提供招待市領導人的菜式,便可實現。當然也有它不好的地方,就是把被訪問者暴露給訪問者,使得訪問者可以直接瞭解被訪問者的所有東西。明白了優缺點,才能更好的在實際中運用,一般訪問者模式運用於要求遍歷多個不同的對象的場景。
推薦閱讀
設計模式系列文章持續更新中,歡迎關註公眾號 LieBrother,一起交流學習。
公眾號後臺回覆『大禮包』獲取 Java、Python、IOS 等教程
加個人微信備註『教程』獲取架構師、機器學習等教程