原創 編程新說李新傑 編程新說 2019-07-22java
老實說,在實際編程中,訪問者設計模式應用的並很少,至少我是這樣認爲的,由於它的主要使用場景並很少。
那麼確定會有人問,訪問者模式的主要使用場景是什麼呢?繼續往下看便知。git
首先要說的是,設計模式中的「訪問者」和現實生活中的「訪問者」其本質是一回事。雖然設計模式中的不太熟悉,但現實生活中的再熟悉不過了。github
我在之前的文章中屢次提到過,有時站在現實生活的角度看待某些技術點反而會更容易看清楚,那照例仍是從生活中的事情提及吧。編程
提及訪問者,我可以想到最高大上的,莫過於國家領導人的國事訪問。以中方訪問美方來講吧,這裏面的大體內容(我猜)應該是這樣的:設計模式
中方專機什麼時間在哪一個機場降落,美方派誰在機場迎接,而後就是歡迎儀式和歡迎晚宴,接着就是會見哪些人,開哪些會議,簽署哪些文件,參觀哪些地方等等,最後就是結束訪問啓程回國。安全
固然這些內容確定是雙方外交部門都提早溝通好的。可是仍然是在美方的安排下一步一步進行,由於咱們是做爲訪客的身份,人家是東道主,要盡地主之誼的。(雖然老美不是什麼好東西)ide
好比人家安排的吃牛排,那咱們就吃吧。咱們總不能要求他們改爲「主席套餐」吧,再說他們的廚師也搞定啊。工具
等到老美的總統來咱們國家訪問的時候,他們就成了訪客了,咱們就是東道主,總體就得由咱們來安排。讓他喝稀飯他就不能吃大米,不喜歡吃就晚上本身回酒店泡方便麪,哈哈哈哈。學習
若是把這個事情抽象一下就是,一方在另外一方的安排下,逐步有序的作一些事情。設計
國事訪問這事啊離咱們太遙遠了,那就再看個和咱們息息相關的吧。沒錯,就是旅遊。不管是國內遊仍是出境遊,其實差異不大,大體內容應該是這樣的:
先報好旅行社,在指定的時間乘坐交通工具到達目的地後,會有一輛大巴車拉着咱們,按照行程開始去景點,去吃飯,去酒店等等。
咱們什麼都不用操心,跟着走就好了,由於旅行社和導遊都安排好了。再說了,即咱們使有意見,導遊也不會聽咱們的。
頗使人討厭的可能就是逛購物店了,可是沒辦法,由於協議已經簽了。咱們有義務進購物店,聽相關人員講解,想買的就買,不想買的隨便看看,可是不能提早出去。
其實還有更坑的,那就是導遊在大巴車上強行收費,說些很難聽的話,甚至罵人/威脅。尤爲是在境外,他們以爲今生很難再見面,有時話說的特別難聽。
因此整個行程下來,既有高興的時候,也有心煩的時候。導遊給咱們講解當地歷史的時候,以爲他是「好人」,領咱們進購物店時,又以爲他是「壞人」。
其實都不是,他是「工人」,一個從事旅遊行業工做的人。一個須要養家餬口的人,跟咱們沒啥區別。我是否是很善解人意啊。
若是把這個事情也抽象一下就是,必須按照既定的規則走完全部事項,若是對某個事項關心,那就積極的去獲取本身想要的信息,若是對某個事項不關心,那就默默的跟隨便可,什麼都不用作,可是不許離開。
我想說的是既然報團遊有如此多的問題,爲何還有那麼多人報團,而不選自由行呢。答案是顯而易見的。
以出境游來講,當你達到國外,人生地不熟,語言又不通,不少事情的推動會特別艱難。
固然也能夠提早研究攻略,制定好路線,訂好酒店機票等。可是旅遊主要是想放鬆一下,爲了出國一週,在家看三個月攻略,豈不是更累嗎?
總結一下,當你對所要作的事情徹底不瞭解,並且想要了解的話需花費很大的精力時,只能選擇第三方給出的方案,雖然明知裏面可能會有坑。
對於像國事訪問的,由於有許多禮儀禮節或規則約束須要遵照,因此通常也都遵從東道主的安排。
雖然出訪和旅遊這兩件事的本質徹底不同,可是他們的宏觀進行模式卻基本一致。
到此咱們已經講了兩件事,兩個特色,兩個緣由。請仔細體會下。看起來有點讓人不爽,但又很有些無奈。
這兩件事都是站在「訪問者」的立場來講的,下面從多角度來看下。
假如小明在北京工做多年,對北京很是熟悉。他的朋友小白來找他玩,並且是第一次來北京,打算去一些有名的景點。
在這件事中,小明就是東道主,小白就是訪客。其實就是一方帶另外一方參觀嘛。
站在東道主的角度,他要安排訪客參觀景點,因此是這樣的:
/** * <p>東道主 */ public interface Host { //帶朋友去故宮 void show(PalaceMuseum PalaceMuseum, Guest guest); //帶朋友去長城 void show(GreatWall GreatWall, Guest guest); //帶朋友去頤和園 void show(SummerPalace SummerPalace, Guest guest); }
站在訪客的角度,他是要參觀景點的,因此是這樣的:
/** * <p>客人 */ public interface Guest { //看故宮 void look(PalaceMuseum PalaceMuseum); //看長城 void look(GreatWall GreatWall); //看頤和園 void look(SummerPalace SummerPalace); }
站在景點的角度,它是要接受訪客的參觀的,因此是這樣的:
/** * <p>故宮 */ public interface PalaceMuseum { //讓訪客看 void accept(Guest guest); } /** * <p>長城 */ public interface GreatWall { //讓訪客看 void accept(Guest guest); } /** * <p>頤和園 */ public interface SummerPalace { //讓訪客看 void accept(Guest guest); }
在這個事件中共有三種角色,它們的職責、目的和做用都很是清晰:
小明:東道主,職責是負責協助
小白:訪客,目的是欣賞景點的景色
景點:被欣賞者,做用是提供景色
這就是一個訪問者的模型,咱們把它抽象並通常化,發現這是一個固定的套路或模式,稱之爲訪問者模式。
在訪問者模式中,共有三方參與者,它們的分工很是明確:
一方:訪問者,獲取信息的人
二方:被訪問者,提供信息的人
三方:協調者,安排一二雙方進行交互的人
能夠這樣來理解三方的定位,一方是購買者(出錢),二方是提供者(出力),三方是協調者(和稀泥)。哈哈。
注意,這裏的一方二方三方都是訪問者模式內部的概念,它們是一家人或一個單位的。
換個角度來看就是,訪問者在協調者制定的規則下完成對被訪問者的訪問,期間獲取關心的信息,忽略不關心的信息。
把訪問者模式放到一個宏觀應用中,應該是這樣的:
用戶程序->|訪問者->協調者->被訪問者|->底層複雜數據
對於設計模式,必定要活學活用,不能拘泥於GOF。必定要按本身的場景需求來用,不能死搬硬套。
在訪問者模式中,一般把被訪問者稱爲元素,訪問者天然仍是訪問者,抽象一下:
//元素 public interface Element<V extends Visitor> { //接受訪問者 void accept(V visitor); } //訪問者 public interface Visitor<E extends Element> { //訪問元素 void visit(E element); }
請注意這裏的泛型。
而後再抽象一下協調者:
public interface ObjectStructure { //全部元素 List<Element> getElements(); //全部訪問者 List<Visitor> getVisitors(); }
協調者擁有全部的元素和全部的訪問者,它能夠本身來實現訪問規則,使訪問者完成對元素的訪問。
注意,個人抽象和GOF的不徹底同樣,由於前面已經說了要活學活用嘛。
那到底是一個訪問者訪問一個元素,仍是一個訪問者訪問多個元素,仍然是沒有標準答案,應該根據實際狀況來定。
好比大公司,一崗(位)一(個)人,事情作得精細。小公司,多崗(位)一(個)人,辦事效率高。各有千秋,適合的纔是最好的。
下面給出一個訪問者訪問一個元素的狀況。
訪問者A訪問元素A:
//元素A public interface ElementA extends Element<VisitorA> { @Override void accept(VisitorA visitor); } //訪問者A public interface VisitorA extends Visitor<ElementA> { @Override void visit(ElementA element); }
因爲上面使用了泛型,這裏的方法參數能夠換爲精確的類型。
訪問者B訪問元素B:
//元素B public interface ElementB extends Element<VisitorB> { @Override void accept(VisitorB visitor); } //訪問者B public interface VisitorB extends Visitor<ElementB> { @Override void visit(ElementB element); }
後續就按照這個模式去擴展便可。有新的數據須要訪問時,就添加新的元素和新的訪問者,同時還可能須要修改協調者。
咱們常常聽到說,要學習西方模式,XX模式,YY模式等,其實主要是學習人家的理念和思想,而不是照抄,由於照抄有水土不服的問題。
因此,每個開發人員或設計人員都不該該直接照抄GOF的設計模式。特別是爲了使用而使用,就更沒意思了。
訪問者模式的主要應用場景之一就是,底層數據過於複雜,是的,過於複雜,上層應用沒法直接訪問。
如Java的字節碼文件,咱們的應用程序根本就沒法直接訪問。
還有一種就是不想讓別人隨意訪問,能夠經過訪問者模式去約束訪問者訪問的方式。
好比我在大四時就去參觀過汽車製造車間,由專人領着咱們按照路線行走,由於隨意亂跑不安全嘛。
訪問者模式的中心思想就是,協調者制定好合理的規則,訪問者按照規則進行訪問,從本身關心的被訪者上獲取須要的數據信息。
固然也能夠採用被動式的,協調者按照必定規則,把被訪問者的信息逐步推送給訪問者,訪問者根據本身的須要來選擇保存或忽略。
最後,設計模式是一種理念,一種思想,須要去思考,去領悟。
程序代碼:
https://github.com/coding-new-talking/java-code-demo.git
(END)