白話設計模式系列之裝飾模式

序言

以下為本人寫的其他設計模式,感興趣的同學可以查閱。

白話設計模式之菜鳥提升篇

此頭條號中已經發布了其他設計模式,感興趣的同學可以關注我後進行查閱,同時獲取後序更多模式及其他信息。

裝飾模式(Decorator Pattern)

動態地給一個對象增加一些額外的職責。在為對象增加額外職責方面,裝飾模式替代了繼承,它比子類繼承父類更為靈活,它用無需定義子類的方式來給對象動態的增加職責,使用對象之間的關聯關係來取代繼承。

模式案例解析

案例:如何實現一功能,可以方便的操作文本中的文字、圖片(如:改變大小、移動位置)。注意:這裡我們不是如何實現文本操作這個功能,而是如何使用裝飾模式來設計這個功能。感興趣的同學可以使用繼承的方式來實現這個功能,然後和我的對比下,這樣更能清晰的理解裝飾模式(裝飾模式在為對象動態增加功能方面優於繼承)。具體類圖如下所示:

Advertisements

裝飾模式

Content(抽象構件類):它是具體構件和抽象裝飾類的父類,聲明了具體構件的業務方法,在案例中它代表了文本裡面的內容(文字、圖片),它定義了抽象方法display()用於顯示內容,具體顯示圖片還是文字由具體的實現類實現。它的使用讓客戶端以同樣的方式來處理具體構件和裝飾后的構件(這屬於典型的面向介面編程,符合面向對象設計原則中的依賴倒轉原則)。

WordsContent、ImagesContent(具體構件):它們實現了Conten定義的display()方法,該方法用於顯示初始的字體大小和圖片大小、文字和圖片初始的位置(文件左上角),裝飾器可以對其增加功能(如改變初始大小、改變初始位置)。

Advertisements

Decorator(抽象裝飾類):它是抽象構件類(Content)的子類,用於增加構件的職責,它需要維護一個抽象構件(Content)的引用,通過該引用可以調用具體構件裝飾前的方法,並通過其子類的實現來對構件進行擴展(增加職責),以達到裝飾的目的。代碼片段如下所示:

Decorator

ChangeSizeDecorator,MoveDecorator(具體裝飾類)它們都實現了Decorator的display()方法,並且在方法里調用了父類的display()方法和增加職責的方法(addOperation())。這裡為啥要調用父類的display方法呢?簡單理解就是先要獲取到需要裝飾的對象(文字、圖片)才能進行裝飾(不同大小/不同位置的文字和圖片)。代碼片段如下所示:

MoveDecorator

ChangeSizeDecorator

Client(客戶端:這裡我們以移動圖片位置,放大文字為例來進行調用,具體代碼片段如下所示:

客戶端調用

客戶端調用結果顯示如下圖所示:

調用結果顯示

擴展

透明裝飾模式、半透明裝飾模式:上述案例就是透明裝飾模式,客戶端所使用的都是Content類型的具體裝飾類、構件,客戶端無法調用具體裝飾類除display外的其他方法,也就是說具體裝飾類對客戶端是透明的;半透明裝飾模式下,客戶端所使用的裝飾類是具體裝飾類的類型,客戶端可以調用裝飾類的所有方法,這也使得程序更加靈活,但是無法像透明裝飾模式一樣可以重複的裝飾已經裝飾過的構件。

注意事項

  • 盡量保持裝飾類和構件的介面相同,這樣對於客戶端來說裝飾前後的構件都是一樣的

  • 構件類盡量保持單一職責,不要使其擁有太多的功能

  • 在只有一個構件類的情況下,可以將抽象裝飾類作為該構件類的子類

總結

優點

  • 對於擴展一個對象的功能來說,裝飾模式比繼承更加靈活,不會導致類的個數急劇增加

  • 可以對對象進行多次裝飾,讓一個對象具備更多的功能

  • 具體構件類和具體裝飾類相互獨立,增加具體構件和具體裝飾類無需修改源代碼,符合開放閉合原則

缺點

  • 比使用繼承複雜,相應的調試和維護成本會增加

  • 使用裝飾模式進行系統設計時將產生很多小對象,這些對象的區別在於它們之間相互連接的方式有所不同,而不是它們的類或者屬性值有所不同,大量小對象的產生勢必會佔用更多的系統資源,在一定程序上影響程序的性能

今天就先寫到這裡,如有問題,歡迎吐槽。在此特別感謝design-pattern-java一書的作者,是他讓我開始對設計模式產生了感覺。地球不爆炸,我們不放假,good good study day day up !!如有幫助請多多關注!點贊

Advertisements

你可能會喜歡