設計模式遺珠(二)

終於終於,我們來到了設計模式學習的最後一篇,是整個乾貨系列的最後一篇了,還真有點捨不得,原來一個設計模式能學習這麼久,也佩服自己的堅持。

期間有過學習寫作課的時間,也有過偷懶的時間,好在都堅持下來了,好在我還在,你還在關注,我們一直都在努力,一直都在進步。

話不多說,先進入今天的主題,來聊聊最後的幾個設計模式。

解釋器模式

解釋器模式:使用解釋器模式(Interpreter Pattern)爲語言創建解釋器。

場景: 還記得我們之前鴨子的例子麼。Duck Pond的模擬器。在這裏,我們可能還想到把它拿來當做兒童學習編程的教育工具。使用這個模擬器,每個孩子都可以用一種簡單的語言來控制一隻鴨子。

比如我們需要使用一門語言來控制鴨子左轉、右轉、甚至是飛翔。那我們現在需要做的事情,就是表現並解釋語法中的句子,好讓學習的同學看到用這個語言控制鴨子的效果。

如何實現: 當你需要實現一個簡單的語言時,就使用解釋器模式定義語法的類,並用一個解釋器解釋句子。每個語法規則都用一個類代表。

這就是一個將鴨子語言轉換成類的例子,特別需要注意的是,類直接映射到語法

要想解釋這種語言,就調用每個表達式類型的interpret()方法。此方法需要傳入一個上下文(Context)----也就是我們正在解析的語言字符串輸入流–然後進行比對並採取適當的動作。

解釋器模式的優點 解釋器的用途和缺點
將每一個語法規則表示成一個類,方便於實現語言 當你需要實現一個簡單的語言時,使用解釋器
因爲語法由許多類表示,所以你可以輕易地改變或擴展此語言 當你有一個簡單的語法,而且簡單比效率更重要時,使用解釋器
通過在類結構中加入新的方法,可以在解釋器的同時增加新的行爲,例如打印格式的美化或者進行復雜的程序驗證 可以處理腳本語言和編程語言
當語法規則的數目太大時,這個模式可能會變得非常繁雜。在這種情況下,使用解析器/編譯器的產生器可能更合適

中介者模式

中介者模式:使用中介者模式(Mediator Pattern)來集中相關對象之間複雜的溝通和控制方式。

場景: 現在是物聯網的時代,未來的生活,智能家居肯定佔有很大的比例。比如,我們在家裏,點擊打盹按鈕,家裏的鬧鐘就會告訴咖啡壺開始煮咖啡。又比如,你需要制定很多方案,週末不供應咖啡、在洗澡前將噴頭關閉15分鐘、在丟垃圾的時候將鬧鐘時刻提前等。

但是,如果我們想要持續地追蹤每個對象的每個規則,以及衆多對象之間彼此錯綜複雜的關係,實在是不容易。

中介者給你助力: 在這個系統中,加入一箇中介者,就會變得簡單。

  • 每個對象都會在自己的狀態改變時,告訴中介者
  • 每個對象都會對中介者所發出的請求做出作出迴應

在沒有中介者的情況下,所有的對象都需要認識其他對象。也就是說,對象之間是緊耦合的。有了中介者之後,對象之間徹底解耦。

中介者包含了整個系統的控制邏輯。當某個裝置需要一個新的規則時,或者是一個新的裝置被加入系統內,其所有需要用到的邏輯也都被加進了中介者內。

中介者模式的優點 中介者的用途和缺點
通過將對象彼此解耦,可以增加對象的複用性 中介者常常被用來協調相關的GUI組件
通過將控制邏輯集中,可以簡化系統維護 中介者模式的缺點是,如果設計不當,中介者對象本身會變得過於複雜
可以讓對象之間所傳遞的消息變得簡單而且大幅減少

備忘錄模式

備忘錄模式:當你需要讓對象返回之前的狀態時(例如,你的有用戶請求“撤銷”),就是用備忘錄模式(Memento Pattern)

場景: 其實看名字,就知道備忘錄是幹什麼的了。現在很多小夥伴都會沉迷於遊戲。當你進入到更高的遊戲關卡,遊戲結束的機率就會提高。

對於想衝擊更高成績的你來說,肯定不希望重頭開始,而且想從你結束的關卡開始。於是,就有了“儲存進度”的命令,好讓玩家能夠存儲遊戲進度,避免不必要的損失,畢竟這可是自己的辛苦所得。

這個“存儲進度”的功能需要設計成能夠復活的角色,而進度停留在上一次的關卡。

備忘錄來助力: 備忘錄模式有兩個重要的目標:

  • 儲存系統關鍵對象的重要狀態
  • 維護關鍵對象的封裝

請不要忘記單一責任原則,不要把保持裝填的工作和關鍵對象混在一起,這樣比較好。這個專門掌握狀態的對象,就成爲備忘錄。

備忘錄模式的優點 備忘錄的用途和缺點
將被存儲的狀態放在外面,不要和關鍵對象混在一起,這可以幫助維護內聚 備忘錄用於存儲狀態
保持關鍵對象的數據封裝 使用備忘錄的缺點:儲存和恢復狀態的過程可能相當耗時
提供了容易實現的恢復能力 在Java系統中,其實可以考慮使用序列化(Serialization)機制儲存系統的狀態

原型模式

原型模式:當創建給定類的實例的過程很昂貴或很複雜時,就是用原型模式(Prototype Pattern)

場景: 我們還是來玩遊戲。當你的英雄人物在動態創建的場景中闖蕩時,遇到了龐大的敵軍有待殲滅。你希望怪獸的特徵能夠隨着場景的變化而演化。

畢竟,如果一隻鳥一樣的怪獸隨着你的角色進入海底,實在是沒有道理。最後,你還希望能夠讓高級用戶創建他們自己的怪獸。

想法: 創建各式各樣的怪獸實例,已經越來越麻煩了。將各種狀態細節放在構造器中,看起來一點都不內聚。如果能夠在單一區域內封裝所有的實例化細節,那該多好。

原型模式來助力: 原型模式允許你通過複製現有的實例來創建新的實例(在Java中,這通常意味着使用clone()方法,或者反序列化)。這個模式的重點在於,客戶的代碼在不知道要實例化何種特定類的情況下,可以製造出新的實例。

原型模式的優點 原型的用途和缺點
向客戶隱藏製造新實例的複雜性 在一個複雜的類層次中,當系統必須從其中的許多類型創建新對象時,可以考慮原型
提供讓客戶能夠產生未知類型對象的選項 使用原型模式的缺點:對象的複製有時有點複雜
在某些環境下,複製對象比創建新對象更有效

訪問者模式

訪問者模式:當你想要爲一個對象的組合增加新的能力,且封裝並不重要時,就是用訪問者模式(Visitor Pattern)

場景: 現在有一家餐廳和一家煎餅屋,他們中的顧客很重視養生。在訂餐之前,都會詢問營養信息。因爲兩個商家都非常願意迎合顧客的需求,有些顧客甚至詳細得連每種原料的營養成分也不放過。

煩惱的地方: 看上圖就知道,這簡直就和潘多拉盒子一樣。天知道我們接下來要加入什麼新方法,而每次一有新方法加入,就必須加到兩個地方。還有,萬一想要加強基本系統,比如說多了食譜類,那又該怎麼辦呢?我們就必須改變三個地方。

訪問者來助力: 訪問者必須參觀組合內的每個元素;這樣的功能是在導遊(Traverser)對象中,訪問者通過導遊的引導,收集組合中所有對象的狀態。一旦狀態被收集了,客戶就可以讓訪問者對狀態進行各種操作。當需要新的功能時,只要加強訪問者即可。

訪問者的優點 訪問者的用途和缺點
允許你對組合結構加入新的操作,而無需改變結構本身 當採用訪問者模式的時候,就會打破組合類的封裝
想要加入新的操作,相對容易 因爲遊走的功能牽涉其中,所以對組合結構的改變就更加困難
訪問者所以進行的操作,其代碼是集中在一起的

結語

難說再見,還是很高興,你我一同堅持到了最後。在學習期間,也有很多朋友加入,甚至很多朋友就是因爲看了我的這個系列才決定關注我的,在這裏,對所有的讀者道一聲感謝。

感謝你們的持續關注,感謝你們的堅持,感謝你們的反饋,讓我能完成對《Head First設計模式》這本書的拆解,雖然拆解的不怎樣,但還是希望能對你有幫助。

我們一直在進步,希望能和你們一起堅定地走下去。加油!

「奔跑吧攻城獅」感謝大家的關注,現在後臺回覆「設計模式」贈你小編精心挑選設計模式書籍。小編最近開竅,組建了一個技術交流羣,回覆「加羣」即可解鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章