跳到主要內容

整理設計模式

        依據 GOF 的書,可以將經典的設計模式分為以下三類:生成、行為、結構。

  • 生成模式:牽涉到將物件實體化。這類模式都提供一個方法,將客戶從所需要實體化的物件中鬆綁出來。
  • 行為模式:模述類別和物件如何互動,以及各自的責任

        有人可能會覺得裝飾者模式明明有替物件增加行為,為什麼不算是行為模式呢?我們可以從上面的結構模式得知,結構模式用來描述類別或物件如何被合成,以建立新的結構或功能。裝飾者模式允許你透過「將某物件包裝進另一個物件的方式」,將物件合成以提供新功能,因此焦點應該放在「動態合成物件,以取得某功能」,而不是物件之間的溝通。

        設入淺出設計模式也有提到一些使用設計模式的思考模式:
  • 保持簡單 (Keep It Simple):儘可能用簡單的方式解決問題。不要認為沒用設計模式就不是好設計,而是有時為了設計簡單而有彈性,需要使用設計模式
  • 設計模式非萬靈丹:需要考慮使用設計模式時,對其他部份造成的影響
  • 要知道何時需要設計模式:通常設計中需要改變的地方就需要採用設計模式。但加入模式是為了實際的改變,不是假定的改變。
  • 重構的時間,就是模式的時間:重構 (Refactoring) 是個好時機,可以檢視你的設計,是否能利用設計模式讓它有更好的結構。
  • 拿掉不需要的設計模式:當你的系統變得非常複雜,且不用預留任何彈性時,就可以拿掉模式。換句話說,就是有簡單的方案時,就可以不用設計模式
  • 現在不需要,就不用設計模式:有實際的需求去支援改變時再使用設計模式。因為採用設計模式,就有機會讓系統變複雜。

留言

這個網誌中的熱門文章

訪問者模式 (Visitor Pattern)

        假設你設計一個系統,其中會有一些相似類別,類別中都有某些方法內容相似,但還是需要判斷目前要做事的是哪個類別才能呼叫對應的適當類別。通常遇到這種情情,在 Java 中最直接的做法就是使用 instanceof 關鍵字來判斷,如以下的簡單範例: public interface CarComponent { public void printMessage(); } public class Wheel implements CarComponent { @Override public void printMessage() { System.out.println("This is a wheel"); } // 這是 Wheel 跟 Engine 不同的方法 public void doWheel() { System.out.println("Checking wheel..."); } } public class Engine implements CarComponent { @Override public void printMessage() { System.out.println("This is a engine"); } // 這是 Wheel 跟 Engine 不同的方法 public void doEngine() { System.out.println("Testing this engine..."); } } public class Car { private List mComponents; public Car() { mComponents = new ArrayList<carcomponent>(); } // 有些時候我們還是需要針對不同類別去做不同的事情 public void setComponent(CarCompon

裝飾者模式 (Decorator Pattern)

        假如你有一間飲料店, 目前只有賣幾種咖啡。因為生意很好, 因此想更換菜單…         以下是目前菜單的類別圖:         簡單說明此類別圖, cost() 是抽象的, 子類別要實作自己的 cost() 來告知飲料的價格。         買咖啡時, 也可要求要加料, 例如牛奶(Milk)、摩卡(Mocha,就是巧克力口味)。這樣的新類別要如何設計呢 ? 看起來是不能直接新增所需的子類別, 例如 EspressoWithMilk, EspressoWithMilkAndMocha, DarkRoastWithMilk, DarkRoastWithMilkAndMocha… 這樣加下去, 日後飲料跟配料越來越多時, 類別也就越多, 這實在不是個好設計。         換個方式設計呢, 在 Beverage 裡面加入所有的配料如何 ? 這樣好像也不太好, 未來要是配料有更動, Beverage 程式碼就要重寫, 而未來要是有新口味的飲料時, 有些配料就不太合理 ( 薑茶加摩卡 ? ), 更麻煩的是, 無法應付機車的客人 (例如要加 3 份牛奶)。這時候裝飾者模式就能上場啦。在介紹裝飾者模式前, 先說明其設計守則: 類別應該開放, 以便擴充 ; 應該關閉, 禁止修改。         我們的目標是允許類別容易擴充, 在不修改現有程式碼的情形就能搭配新的行為。這樣的設計具有彈性, 可以接受新功能以達到改變需求的目的。這看起來好像有點矛盾, 但是的確有一些技術可以在不直接修改程式碼的情形下進行擴充, 如裝飾者模式。         這時候應該有人會問: 那是不是以後我的專案架構設計都遵循這個守則就是好設計了 ? 答案是不太可能, 也沒這必要, 就算做得到, 也可能是浪費, 容易導致程式碼複雜且難以理解。只需小心選擇哪些部分未來會擴充, 這些部份遵循這個設計守則即可。         接下來正式介紹裝飾者模式的定義:  裝飾者模式動態地將責任加諸於物件上。若要擴充功能,裝飾者模提供了比繼承更有彈性的選擇 Attach additional responsibilities to an object dynamically. Decorators provide a flexible alt