訪問者模式:從介紹到實踐
百萬級高并發(fā)WebRTC流媒體服務(wù)器設(shè)計與開發(fā)
download:https://www.zxit666.com/1305/
01什么是訪客模式?
訪問者模式的定義如下,是指在不改變數(shù)據(jù)結(jié)構(gòu)的情況下,提前定義新的操作。
封裝了一些作用于數(shù)據(jù)結(jié)構(gòu)中元素的操作,可以在不改變數(shù)據(jù)結(jié)構(gòu)的情況下定義作用于這些元素的新操作。
但在實際應(yīng)用中,我發(fā)現(xiàn)有些例子并非如此。在一些例子中,沒有穩(wěn)定的數(shù)據(jù)結(jié)構(gòu),但有穩(wěn)定的算法。在亦舒看來,訪客模式是:固定不變的,開放可變的。
先說一個生活中的例子:一個科學(xué)家憑記憶面試。眾所周知,科學(xué)家在接受采訪時,肯定有一些程序上的限制。你是不可能隨便提問的。我們假設(shè)這個過程是:先問科學(xué)家的學(xué)校經(jīng)歷,再談你的工作經(jīng)歷,最后談你的科研成果。那么這個過程中固定的是什么呢?固定的是面試流程。有什么變化?改變的是,不同的記者可能會根據(jù)他們的學(xué)校經(jīng)歷提出不同的問題。
按照我們之前的理解,訪客模式其實就是把不可改變的東西固定下來,把變化打開。然后我們可以抽象出科學(xué)家的采訪。
首先需要有一個Visitor類,定義了一些外部(記者)可以做的事情(提問學(xué)校經(jīng)歷、工作經(jīng)歷、科研成果)。
公共接口訪問者{
public void askSchoolExperience(字符串名);
public void askWorkExperience(字符串名);
public void askScienceAchievement(字符串名);
}
然后聲明一個XinhuaVisitor類來實現(xiàn)Visitor類,意思是新華社的一個記者(訪問者)要訪問科學(xué)家。
公共類XinhuaVisitor實現(xiàn)訪問者{
@覆蓋
public void askSchoolExperience(字符串名稱){
System.out.printf("請問%s:你在學(xué)校最大的成就是什么?n ",名稱);
}
@覆蓋
public void askWorkExperience(字符串名稱){
System.out.printf("請問%s:工作中最難忘的事是什么?n ",名稱);
}
@覆蓋
public void askScienceAchievement(字符串名稱){
System.out.printf("請問%s:最大的科研成果是什么?",姓名);
}
}
然后聲明一個科學(xué)家類,說明是科學(xué)家。科學(xué)家通過一個accept()方法接收記者(訪問者)的采訪申請并存儲。科學(xué)家定義了一種面試方法,把面試過程固定死。只有我教你問什么,我才會讓你(記者)提問。
公共類科學(xué)家{
私人訪問者訪問者;
私有字符串名稱;
私人科學(xué)家(){}
公共科學(xué)家(字符串名稱){
this.name = name
}
公共void接受(訪問者訪問者){
this.visitor =訪問者;
}
公開無效面試(){
system . out . println("-");
System.out.println(" -開始說學(xué)校經(jīng)歷-");
visitor.askSchoolExperience(姓名);
System.out.println(" -開始說工作經(jīng)歷-");
visitor.askWorkExperience(名稱);
System.out.println(" -開始說科研成果-");
visitor.askScienceAchievement(姓名);
}
}
最后,我們聲明一個場景類客戶端來模擬面試過程。
公共類客戶端{
公共靜態(tài)void main(String[] args) {
科學(xué)家楊=新科學(xué)家();
yang . accept(new XinhuaVisitor());
yang . interview();
}
}
操作的結(jié)果是:
-訪問開始
-開始談?wù)搶W(xué)校經(jīng)歷-
請問,楊振寧:你在學(xué)校最大的成就是什么?
-開始談?wù)摴ぷ鹘?jīng)歷-
請問楊振寧:你在工作中最難忘的觀點是什么?
-開始談?wù)摽蒲谐晒?
請問楊振寧:最大的科研成就是什么?
看到這里,大家對訪客模式的本質(zhì)(固定不變,開放可變)有了更感性的認識。在這個例子中,不變的、固定的是面試過程。改變的是你可以問不同的問題。
一般來說,訪問者模式的類結(jié)構(gòu)如下圖所示:
訪問者訪問者界面。訪問者定義訪問者可以做什么。這就需要你分析什么是可改變的,把這些可改變的內(nèi)容抽象成一個訪問者接口方法,把它開放出來。被訪問者的信息實際上是通過訪問者的參數(shù)傳遞的。
具體訪問者。特定訪問者定義了特定類型訪問者的實現(xiàn)。對于新華社記者來說,他們更關(guān)心楊振寧的科學(xué)成就,所以提問時更傾向于挖掘成就。但對于青年報記者來說,他們的讀者是青少年,他們更關(guān)注楊振寧在學(xué)習(xí)和工作中的精神。
元素具體元素。這指的是特定的被訪問的類,在我們的例子中,是科學(xué)家類。一般情況下,我們會提供一個accept()方法來接收訪問者參數(shù),這將相當(dāng)于接受它的模型應(yīng)用。然而,這種方法不是必需的。只要能得到visitor對象,就可以定義這個參數(shù)傳遞。
對于訪問者模式,最重要的是訪問者、具體訪問者和元素。Visitor和ConcreteVisitor定義了訪問者具體能做什么,被訪問者的參數(shù)通過參數(shù)傳遞給訪問者。元素通過各種方法獲取被訪問的對象,通常是通過accept()方法,但這不是絕對的。
應(yīng)該注意的是,我們對設(shè)計模式的研究側(cè)重于理解類之間的關(guān)系以及它們所傳達的信息。至于如何傳遞,是通過accept()方法還是通過構(gòu)造函數(shù),都不是重點。