如何從分類層面,深入理解設計模式?

文章首發於公眾號「架構師指南」及個人部落格 shuyi.tech,歡迎關注訪問。

文章首發於公眾號「架構師指南」及個人部落格 shuyi.tech,歡迎關注訪問。

學習過設計模式的都知道,設計模式分為三大類,分別是:創建型、結構型、行為型。但為什麼它們這麼分呢?某個設計模式為啥就屬於結構型,而不屬於行為型呢?創建型、結構型、行為型它們到底有什麼不同呢?今天就來聊一聊我的理解。

創建型模式

創建型模式,顧名思義就是用來創建對象的。 創建型模式包含的五個設計模式,分別是:

創建型設計模式

從它們的作用來看,它們全部都是創建新對象相關的模式。

工廠方法模式、抽象工廠模式、建造者模式都是創建新對象,可以屏蔽創建對象的細節。原型模式是進行對象克隆,也算是新對象創建。單例模式是控制只能創建單個對象,其也包含了對象的創建,因此也算是創建型模式。

結構型模式

結構型模式,就是介紹如何將對象和類組裝成較大的結構,並同時保持結構的靈活和高效。結構型模式把一個個對象結合在一起,就像積木搭建起來一樣,有一種結構化的感覺。 結構型模式包含 7 個設計模式,分別是:

結構型模式

適配器模式 指的是可以讓不兼容的對象能夠合作,通常情況是有一個適配器類實現了多個介面,從而在介面方法中寫入特定邏輯去做兼容適配。這裡的結構體現在對於兩種對象的兼容,通過兼容將新老對象組合起來了。

橋樑模式 其實就是把固定的和變化的分離開來,使用組合的方式去實現。將固定的放在原地不動,而變化的則抽離出去作為一個新的類,再通過組合的形式被老的類引用。這裡的結構體現在舊類對新類的引用,它們之間變成了一種結構型關係。

組合模式 就是多個結構組合起來,形成一個更複雜的結構。組合模式更多是一種數據結構的呈現,而不能說是一種設計模式。但從廣義的設計模式定義來看,將組合模式說成是一種設計模式,也沒有錯。

大家會發現組合模式和橋樑模式非常像,其實這兩者之間並沒有太大的差別,甚至是說基本一樣。橋樑模式與組合模式,其實都是基於組合這種關係,不同的對象組合起來形成更大的結構體。橋樑模式是基於組合模式的。

裝飾模式 指的是使用很多其他類對原有類進行功能增強,就像美顏APP一樣,我們使用很多濾鏡對照片進行功能增強。這一個個的濾鏡就嵌套在原有的照片上,就像一個個功能增強類嵌套在原有的基礎類上一樣。裝飾模式的結構性就體現在這種嵌套關係上,一層層的嵌套組成了一種結構。

門面模式 指的是提供一個全新的介面層,將子系統複雜的介面內容屏蔽了。則像是肯德基的前台一樣,幫你把一切複雜的東西屏蔽了。你不需要關心漢堡怎麼做,奧爾良雞翅怎麼做。你只需要告訴前台要吃什麼,它就會把漢堡、雞翅等東西做好了拿給你。

在門面模式中,我們在使用方與子系統之間插入了一層介面層,去屏蔽複雜的內部細節。就像是肯德基的前台,幫我們屏蔽了內部食物的製作細節一樣。門面模式的結構就體現在我們插入的這一層「門面」上,它將使用方與子系統連接起來,讓使用更方便了!

享元模式 指的是共享同一個元素,是一種節省記憶體的設計模式,其實就類似我們的池技術。與其他對象複雜的結構相比,我都不覺得享元模式是一種設計模式,而只是一種思想而已。但如果嚴格地從設計模式的定義來講的話,那其實也可以算是。

在享元模式中,我們會新增一個類去保存元素的映射池。而這個新增的類就相當於是一個新增的對象,通過組合的形式去節省記憶體的消耗。享元模式的結構性更多是通過組合的形式體現的。

代理模式 其實就是一個代理卡在買賣雙方中間,做一些流程上的控制。代理模式的結構性就體現在多了一個代理類,卡在「買賣雙方」中間,這種結構特徵不言而喻。

從上面我們的描述來看,我們可以知道結構型模式很多時候,就是兩者對象之間有一個對象擋在中間,例如:適配器模式、門面模式、代理模式。要不就是通過某些關係組合在一起,例如:橋樑模式、組合模式、裝飾模式、享元模式。

文章首發於公眾號「架構師指南」及個人部落格 shuyi.tech,歡迎關注訪問。

行為型模式

要理解行為型模式,就要重點留意行為。雖然行為型模式有些點與結構型模式類似,但是其最大的特點是行為,是這個動起來的東西。

我們舉個例子:為什麼中介者模式屬於行為型模式,而代理模式屬於結構型模式?

中介者模式聽起來與代理模式很像,但中介者模式說的是做多個對象之間的協調工作,協調他們的行動!看到了嗎?協調他們的行動,才是中介者模式的核心,所以說中介者模式才是行為型模式。而代理模式,則不會有那麼多個對象之間複雜的關係,其側重於對被代理對象的控制。其重點不在於複雜的對象關係,不在於協調多個對象的工作,而在於單個對象的控制,代理就像卡在兩者中間的一個結構一樣。

有些朋友要說了,那其實代理模式也有對代理對象的控制這一行為啊,為什麼不能算是行為型模式呢?代理模式確實有對代理對象控制這一行為,但這裡要強調的是重點這個詞。這裡並不是說代理模式就沒有行為,而是說代理模式的行為比起結構性少,並且不是重點。而中介者模式肯定也有結構性的東西,但它誕生的目的就是為了協調多個子系統的複雜調用關係,協調關係才是中介者模式的重點。

行為型模式有 10 個設計模式,分別是:

責任鏈模式,是一個個對象組合起來的對象鏈。 其請求會從鏈頭傳到鏈尾,每個對象可以判斷其是否返回或傳遞到下一個對象。其側重於是否返回或傳遞下去,重點是在這個行為的處理。所以責任鏈模式才叫行為型模式。

命令模式,是把要做的事情抽象起來,形成一個命令。 後續要做這個事情的時候,我直接給一個命令你就知道我要做什麼了。為什麼要這麼做呢?因為變化!如果我們的命令有很多個,那麼每次我修改一個命令,我就要修改發出命令和執行命令兩個地方。

但實際上發出命令的動作是不會變的,變化的只是執行命令的地方。於是為了隔離變化,那麼我們將執行命令這塊分離出去。那麼發出命令與執行命令怎麼溝通呢?答案是通過命令!這個其實就類似於餐廳前台與後廚的溝通。餐廳前台給的做菜單就是一個命令,後廚拿到這個命令之後就去執行。

可以看到在命令模式里,其核心是拿到命令去執行,它們之間也是一個行動的概念,因此命令模式也才歸屬於行為型模式。

迭代器模式,其實就是實現了集合所有元素的遍歷,讓你使用的時候不需要關心它底層的數據結構。 其重點在於對集合元素的遍歷這個行為,所以歸屬於行為型模式。在現在基本上只存在於源碼、框架中,實際工作用到的很少了。

中介者模式,前面說過了其側重於對多個對象之間的協調。 其重點在於協調這個事情,所以其歸屬於行為型模式。

備忘錄模式,就是在某個時候把東西記下來,避免忘記了。 在編程上,其實就是在某個時刻將對象的資訊記錄保存下來,從而在另一個時候可以恢復。其重點在於,其實現上會有一個專門的類來幫你記錄下資訊,所以歸屬於行為型模式。

觀察者模式,從其名字可以知道有些人盯著你,需要知道你的動向,其實就是發布訂閱模式。 其重點在於觀察這個動作,觀察之後將這個事情傳遞出去,你看到這些都是一個個的動作,因此歸屬於行為型模式。

狀態模式,就是更為方便地控制狀態。 如果一個事物的狀態轉換比較複雜,那麼可以將其狀態抽離出來,單獨作為一個類。這樣其狀態的變化就可以更好地控制,也分離了變化。這個就是狀態模式的應用。從名字來看,我們會覺得它應該是結構型模式,即包含某狀態嘛。但實際上,其側重於對於狀態更好地控制,所以歸屬於行為型模式。

策略模式,其實就是對於不同的東西,用不同的處理方式。 一般情況下,單個具體的策略就是一個類,而這些類都會實現這些策略共有的一個介面。其重點在於不同東西,不同的處理方式。重點在於處理方式的不同,所以歸屬於行為型模式。

模板方法模式。 這裡有兩個詞,即:模板、方法。模板指的是一套固定的東西,其實就是固定的額演算法。方法,表示這個模板是存放在方法上的。所以叫模板方法。簡單地說,模板方法其實就是父類定義了介面類的一些共有演算法。子類不能改變這個演算法流程,只能做有限的擴展。所以模板方法的重點是父類控制了一整套行為流程,其核心在於有一套固定了的演算法行為,所以叫行為型模式。

訪問者模式。 訪問,即當你當成了外人,不想你隨便動。你要什麼,我弄好之後給你(調用你的方法)。其定義的還是訪問者與被訪問者之間應該如何溝通的問題,所以歸屬於行為型模式。

總結

為什麼要費盡周折從分類上去說這些設計模式呢?因為這樣能更好地理解設計模式。 一個設計模式能歸屬於某個分類,我相信並不是巧合,肯定是因為其特性是符合這個分類的,不然不可能隨便地進行分類。

所以我們去研究為什麼這個模式歸屬於這個分類,可以更好地理解這個模式的本質,使得我們對這些設計模式有更好的理解。與此同時,我們在研究的過程也是深入理解的過程,也是對比的過程,不斷加深我們的理解與認知。

但囿於個人對於知識的理解程度不同,可能我在某些模式上的理解也並不是很透徹,有些解釋可能會有點牽強,甚至望文生義。所以大家看的時候還是得批判性地讀。如果有更好的解釋,可以留言告訴我,我們一起深入討論。

文章首發於公眾號「架構師指南」及個人部落格 shuyi.tech,歡迎關注訪問。