我們暫時停下介紹下一個設計模式。本篇將再回頭審思一些設計模式中的基礎以及討論各種原則與策略。
接下來我們會提到:
簡單地說,開閉原則可以如此理解:模組、方法和類別應該對擴展開放,對修改封閉。
回想 Bridge 模式,我們在當時就有實踐這個原則。我們可能不修改已有的類別而增加新的實作(擴展該軟體)。開閉原則主要是期許將新的功能作為單獨的模組加入到系統中。
理想上是希望如此做,但實際可能仍會改動到舊有程式碼,但是當我們愈遵守此原則,軟體對新需求的適應度就會更高。
在先前提過,在程式設計時,先不要進到細節,我們應該建立整體的概念。一樣拿 bridge 模式來做例子,我們回去看 bridge 模式的 UML 可以發現: 再決定如何設計 Implementation
類別的介面時,需要考慮其背景 —— 從 Abstraction
衍生的類別要如何使用這些 Implementation
類別。
回想介紹 bridge 模式時提到的例子(選擇需要的繪圖程式繪製形狀)。這裡我們是先去理解形狀的需求,而這些形狀(抽象 Abstraction
)因而決定繪圖程式(實作 Implementation
)的行為。
在為實作開發介面時,要考慮到具體抽象中所說明的概念的需求。這就是所謂的相依倒置原則:
里氏替換原則是這麼說的:
一個從基礎類別產生的衍生類別應該支援基礎類別的所有行為。
本書作者進一步描述:
只要可能,我喜歡將這一原則擴展為:讓使用物件甚至無法知道是否存在衍生類別。
如此所有的衍生類別都可以是彼此互換的,而對類型進行良好的封裝。
作者說:
我的設計目標之一就是不讓一個類別封裝兩個要變化的事物,除非這些變化明確地耦合在一起。
如果這麼做,將提高內聚性與降低耦合。我們接下來看一下先前學過的設計模式是如何封裝變化的。
Bridge 模式中的實作除了可以透過一個公開介面存取,新的實作也可以透過再此介面中實作相關功能加入系統。
Abstract factory 模式封裝的變化是哪些物件組可以實體化。本模式也隱藏了如何建立物件的所有變化,因此,當我們因應需求改變實體化物件組的時候,只需要改變實作方式即可(工廠介面不變)。
Adapter 模式可以用來把截然不同的物件依照需要放進一個公開的介面。
一般來說,facade 模式不會封裝變化。但也有可能有種情境是:出現了另一套子系統,新的子系統也要依照相同的介面建立。在這個情況會結合 facade 模式與 adapter 模式。此時,facade 模式就會隱藏了子系統的變化。
簡單來說就是:夢很美,但是醒來還是得上班。(????)
咳咳。正經的說,因為設計模式與相關的程式設計原則都是一般性原則,所以切勿當唯一真理,有時候仍然是需要依照自己的需求,做適當的調整。
下表是常會產生的錯誤:
錯誤 | 產生條件 |
---|---|
浮於表面 | 僅僅對低層情況有了一些膚淺的理解,就草草選擇了一個模式 |
偏見 | 對模式過於偏信。根據已經選定的模式/模型來解釋所有資料,不願意對自己的偏見有任何質疑 |
錯選 | 不理解模式的適用背景與條件而選擇了錯誤的模式 |
誤判 | 不了解模式而造成誤判 |
削足適履 | 硬要套上模式,忽略實際的、具體實體行為中的例外狀況。這會讓建模出的物件過於僵硬 |
下篇我們將繼續介紹下一個設計模式:Decorator 模式。明天見囉!