2個觀點,帶你重新理解設計模式

文章首發於個人博客 shuyi.tech,歡迎點擊原文跳轉閱讀。

設計模式說白了就是傳統經驗的總結,它能讓我們在合適的場景使用合適的模式,從而加快我們的編程速度,也能提高系統的擴展性、穩定性。這裡我想就設計模式提出兩個觀點:

1、設計模式是用來承載複雜的業務邏輯的。
2、用好設計模式需要從變化的角度去理解業務。

設計模式用於承載複雜的業務邏輯

如果你的業務非常簡單,那麼基本上是不需要用到設計模式的。只有當你的業務變得複雜的時候,這才需要用到設計模式。這也是為什麼設計模式總是和重構一起被提到,因為重構的時候就說明這個系統相對比較複雜了,不然也不會做崩了。

那為什麼說設計模式用於承載複雜業務呢?

我們都知道設計模式都有一個類圖,這些類圖其實用於表示這種模式對於變化的分離(關於變化在下文會說到)。設計模式使用類圖來存儲複雜的業務關係,使得開發者可以專註於業務邏輯的開發,所以說設計模式用於承載複雜的業務。

如上圖所示是策略模式的類圖,Context 類是上下文類,在該類中初始化了具體的策略。Strategy 則是策略接口,ConcreteStrategies 則是具體的策略類。這個類圖使用 Strategy 與 ConcreteStrategies 的實現關係,將不同策略隔離開來,開發者不需要去關心策略彼此的關係。而使用 Context 與 Strategy 的關係隔離開來,開發者不需要去關心怎麼選擇策略。所以說 Strategy 與 ConcreteStrategies 的關係、Context 與 Strategy 的關係(類關係)承載了一些邏輯,而就是我所說的:設計模式承載了複雜的業務邏輯。

使用設計模式去承載複雜的業務邏輯,有好也有壞,但總體來說好處比較多。壞處就是對初學者非常不友好,可能他們完全看不懂代碼。好處則是熟悉設計模式的人,用設計模式可以一目了然地知道業務關係,它們使用設計模式作為語言來表達業務的關係。其次,各塊代碼之間相互隔離,穩定性、擴展性非常好。

從變化的視角去理解業務

我工作了5、6年,本該學什麼東西都很快。但我卻依舊花了一兩個月的時間,慢慢琢磨每個設計模式的本質。經過一段時間的琢磨,我發現了一個理解設計模式的全新視角:變化。

很多時候我們去理解一個設計模式,我們不能僅僅知道它的類圖是怎樣的,這樣的學習完全流於表面。我們需要知道它為什麼要這麼做?它這樣做的原因是什麼?它在什麼場景下使用?經過這樣的一番思考,我發現:所有設計模式的誕生,都是為了隔離變化。

在應用的時候,我們需要去分析需求中哪些是變化的,哪些是固定的。然後使用設計模式去承載變化的東西,封裝固定的東西。

工廠方法模式,本質上是為了隔離創建者與使用者。為什麼?因為創建者可能是多變的,而使用者則是確定的。

抽象工廠模式,本質上是為了隔離產品族。為什麼?因為產品族相對是多變的,所以要把變化的東西剝離出去。

橋樑模式,本質上是為了將實現剝離出去。為什麼?因為實現是多變的,而抽象則是確定的,所以要剝離出去。

代理模式,本質上是為了將多變的控制玻璃出去。為什麼?因為代理本身是為了增強對目標對象的控制,那其控制的標準可能就很多,今天可能要這個條件,明天可能要那個條件。因此需要將變化的東西剝離出去,因此有了代理類。有了代理類,我們不會污染目標類。

責任鏈模式,變化的是對於責任的處理。

命令模式,變化的可能是命令的具體做法、執行標準。

迭代器模式,不變的是迭代模式,變化的是不同的數據結構,迭代算法不一樣。

中介者模式,變化?關聯?更多是幫助梳理關係。

備忘錄模式,變化?沒有特別大,其實就是對於類的狀態記錄,單獨由一個類來控制。

觀察者模式,變化?對於觀察後的處理是不同的,是變化的。相同的是,他們都要觀察獲取觸發。

狀態模式,變化的是這些狀態。

策略模式,變化的是這些具體的做法。

模板方法,變化的是具體的某個細節實現,不變的是整個流程算法。

訪問者模式,變化的是不同的訪問對象,不變的是我自身的處理流程(例如文件樹的遍歷)。

那我們應該如何從「變化」的角度去分析業務呢?有什麼可遵循的套路嗎?有什麼最佳實踐嗎?

首先,我們還是應該從業務的複雜度入手,看看業務是否足夠複雜。設計模式的本質是用來承載複雜的業務結構,如果業務目前還不清晰,並且也很簡單,那就不要用設計模式了。

其次,我們還是應該從變化這個角度入手,分析業務系統中哪些是變化的,哪些是不變的。這個就要求你對業務非常熟悉,只有熟悉業務才能弄清楚變化在哪裡。

最後,分析這種變化的各個實體關係,看看是否符合訪問者模式的特徵(有固定的成分,又需要變化,又不是繼承關係)。