【設計模式】趣說訪問者模式,頗有些無奈之舉

来源:https://www.cnblogs.com/lixinjie/archive/2020/05/24/a-post-about-designpattern-of-visitor.html
-Advertisement-
Play Games

老實說,在實際編程中,訪問者設計模式應用的並不多,至少我是這樣認為的,因為它的主要使用場景並不多。那麼肯定會有人問,訪問者模式的主要使用場景是什麼呢?繼續往下看便知。新聞聯播看多了之後首先要說的是,設計模式中的“訪問者”和現實生活中的“訪問者”其本質是一回事。雖然設計模式中的不太熟悉,但現實生活中的 ...



老實說,在實際編程中,訪問者設計模式應用的並不多,至少我是這樣認為的,因為它的主要使用場景並不多。

那麼肯定會有人問,訪問者模式的主要使用場景是什麼呢?繼續往下看便知。


新聞聯播看多了之後


首先要說的是,設計模式中的“訪問者”和現實生活中的“訪問者”其本質是一回事。雖然設計模式中的不太熟悉,但現實生活中的再熟悉不過了。

我在以前的文章中多次提到過,有時站在現實生活的角度看待某些技術點反而會更容易看清楚,那照例還是從生活中的事情說起吧。

說起訪問者,我能夠想到最高大上的,莫過於國家領導人的國事訪問。以中方訪問美方來說吧,這裡面的大致內容(我猜)應該是這樣的:

中方專機什麼時間在哪個機場降落,美方派誰在機場迎接,然後就是歡迎儀式和歡迎晚宴,接著就是會見哪些人,開哪些會議,簽署哪些文件,參觀哪些地方等等,最後就是結束訪問啟程回國。

當然這些內容肯定是雙方外交部門都提前溝通好的。但是仍然是在美方的安排下一步一步進行,因為我們是作為訪客的身份,人家是東道主,要盡地主之誼的。(雖然老美不是什麼好東西)

比如人家安排的吃牛排,那我們就吃吧。我們總不能要求他們改成“主席套餐”吧,再說他們的廚師也搞定啊。

等到老美的總統來我們國家訪問的時候,他們就成了訪客了,我們就是東道主,整體就得由我們來安排。讓他喝稀飯他就不能吃大米,不喜歡吃就晚上自己回酒店泡速食麵,哈哈哈哈。

如果把這個事情抽象一下就是,一方在另一方的安排下,逐步有序的做一些事情。


自己想體驗的話就來個這吧


國事訪問這事啊離我們太遙遠了,那就再看個和我們息息相關的吧。沒錯,就是旅游。無論是國內游還是出境游,其實差別不大,大致內容應該是這樣的:

先報好旅行社,在指定的時間乘坐交通工具到達目的地後,會有一輛大巴車拉著我們,按照行程開始去景點,去吃飯,去酒店等等。

我們什麼都不用操心,跟著走就行了,因為旅行社和導游都安排好了。再說了,即我們使有意見,導游也不會聽我們的。

頗令人討厭的可能就是逛購物店了,但是沒辦法,因為協議已經簽了。我們有義務進購物店,聽相關人員講解,想買的就買,不想買的隨便看看,但是不能提前出去。

其實還有更坑的,那就是導游在大巴車上強行收費,說些很難聽的話,甚至罵人/威脅。尤其是在境外,他們覺得此生很難再見面,有時話說的特別難聽。

所以整個行程下來,既有高興的時候,也有心煩的時候。導游給我們講解當地歷史的時候,覺得他是“好人”,領我們進購物店時,又覺得他是“壞人”。

其實都不是,他是“工人”,一個從事旅游行業工作的人。一個需要養家糊口的人,跟我們沒啥區別。我是不是很善解人意啊。

如果把這個事情也抽象一下就是,必須按照既定的規則走完所有事項,如果對某個事項關心,那就積極的去獲取自己想要的信息,如果對某個事項不關心,那就默默的跟隨即可,什麼都不用做,但是不准離開。


做一個善於思考總結的人


我想說的是既然報團游有如此多的問題,為什麼還有那麼多人報團,而不選自由行呢。答案是顯而易見的。

以出境游來說,當你達到國外,人生地不熟,語言又不通,很多事情的推進會特別艱難。

當然也可以提前研究攻略,制定好路線,訂好酒店機票等。但是旅游主要是想放鬆一下,為了出國一周,在家看三個月攻略,豈不是更累嗎?

總結一下,當你對所要做的事情完全不瞭解,而且想要瞭解的話需花費很大的精力時,只能選擇第三方給出的方案,雖然明知裡面可能會有坑。

對於像國事訪問的,因為有許多禮儀禮節或規則約束需要遵守,所以一般也都聽從東道主的安排。

雖然出訪和旅游這兩件事的本質完全不一樣,但是他們的巨集觀進行模式卻基本一致。

到此我們已經講了兩件事,兩個特點,兩個原因。請仔細體會下。看起來有點讓人不爽,但又頗有些無奈。

這兩件事都是站在“訪問者”的立場來說的,下麵從多角度來看下。


從一個具體的示例說起


假如小明在北京工作多年,對北京非常熟悉。他的朋友小白來找他玩,而且是第一次來北京,打算去一些有名的景點。

在這件事中,小明就是東道主,小白就是訪客。其實就是一方帶另一方參觀嘛。

站在東道主的角度,他要安排訪客參觀景點,所以是這樣的:

/**
 * <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。一定要按自己的場景需求來用,不能死搬硬套。

在訪問者模式中,通常把被訪問者稱為元素,訪問者自然還是訪問者,抽象一下:

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 事務的使用方式 事務的錯誤處理 WATCH命令 生存時間 緩存策略 Redis中的事務(transaction)是一組命令的集合。事務同命令一樣都是Redis的最小執行單位,一個事務中的命令要麼都執行,要麼都不執行。 事務的原理是先將屬於一個事務的命令發送給Redis,然後再讓Redis依次執行這些 ...
  • 摘要 本文旨在瞭解MySQL InnoDB引擎如何支持事務的隔離級別。 文章主要內容分兩個部分。 第一部分闡述資料庫的併發問題以及為之產生的ANSI SQL 標準隔離級別。 第二部分根據 MySQL 官方文檔解釋 InnoDB 是如何支持這些隔離級別的。 資料庫事務的併發問題 ANSI SQL 隔離 ...
  • 從 Gradle 角度看,Android 插件是由 Google 的 Android 團隊開發的一個第三方插件。 從 Android 的角度看,Android 插件是基於 Gradle 構建的,是和 Android studio 完美搭配的新一代構建系統。 ...
  • 目錄:andorid jar/庫源碼解析 Apktool.jar: 作用: 1、用於對APK文件進行解包,成可以讀的smali和xml,png等資源文件。 2、同時,把解碼之後的數據,重新打包成APK文件。 慄子: 使用命令的方式使用 1、apktool d xxx.apk // 解碼 apk文件 ...
  • 一,JavaScript是什麼? 1,JavaScript簡稱:js,是一種瀏覽器解釋型語言,嵌套在HTML文件中交給瀏覽器解釋執行。主要用來實現網頁的動態效果,用戶交互及前後端的數據傳輸等。 2,JavaScript 組成 1,核心語法 - ECMAScript (ES5-ES6) 規範了Java ...
  • 在開發大型Web應用或複雜交互的網站,不免會遇到一些頁面性能瓶頸的問題。本篇介紹一下如何利用Chrome的性能面板分析網站的性能瓶頸,應該對你有所幫助。 註意,為了減少一些Chrome插件對性能評估產生噪音,最好打開隱身模式訪問頁面進行測試。 將Chrome切換到隱身模式,然後打開該頁面進行測試: ...
  • 在組件特定時期,觸發的條件,統稱為生命周期; + 組件生命周期分為三部分: 組件創建階段 :組件創建階段的生命周期函數,有一個顯著的特點:創建階段的生命周期函數,組件一生只執行一次; componentWillMount:組件將要被掛載,此時還沒有開始渲染虛擬dom render:第一次開始渲染真正 ...
  • # 6.動畫 - 1. transition 過渡 transition-property:all;//監聽屬性 transition-duration:1s;//過渡時間 transition-timing-function:linear;//運動速率 transition-delay:1s;// ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...