【设计模式】装饰者模式 ( 概念 | 适用场景 | 优缺点 | 与继承对比 | 定义流程 | 运行机制 | 案例分析 )
文章目錄
- I . 裝飾者模式概念
- II . 裝飾者模式適用場景
- III . 裝飾者模式優缺點
- IV . 裝飾者模式與繼承對比
- V . 裝飾者模式相關設計模式
- VI . 裝飾者模式四個相關類
- VII . 裝飾者模式實體裝飾者類運行機制
- VIII . 裝飾者模式定義使用流程 ( 重點 )
- IX . 裝飾者模式 案例
I . 裝飾者模式概念
裝飾者模式概念 :
① 設計模式類型 : 結構性 ;
② 概念 : 不改變原有類的對象 , 動態地將額外的功能附加到該對象上 ;
③ 擴展對象功能 : 這種功能擴展方式比類繼承更加靈活 ;
④ 裝飾者模式 : 移除類中的被裝飾功能 , 將被裝飾類簡化 , 區分類的核心職責 和 裝飾功能 ;
II . 裝飾者模式適用場景
裝飾者模式適用場景 :
① 功能擴展 : 為一個類擴展功能 , 為其添加額外的職責 ; ( 強調擴展 )
② 動態添加撤銷功能 : 為一個對象動態添加額外功能 , 同時這些被添加的功能還能被動態撤銷 ; ( 強調動態 )
III . 裝飾者模式優缺點
裝飾者模式優點 :
① 擴展靈活 : 使用裝飾者模式 , 比繼承更加靈活 ; 使用裝飾者模式擴展類功能 , 不會改變原來的類 ;
② 排列組合 : 對裝飾類進行各種排列組合 , 可實現不同的擴展功能 ;
③ 開閉原則 : 裝飾者模式符合開閉原則 , 被裝飾的類 , 和裝飾類相互獨立 , 互不干擾 ;
裝飾者模式缺點 :
① 程序復雜 : 需要編寫更多的代碼 , 生成更多的類 , 程序的復雜性增加了 ;
② 動態 / 多層 裝飾 : 動態 / 多層 裝飾一個類時 , 程序更復雜 ;
IV . 裝飾者模式與繼承對比
繼承與裝飾者模式對比 :
① 繼承復雜 : 使用繼承擴展功能 , 需要生成很多子類 , 系統復雜性增加 ;
② 繼承靜態 : 繼承在編譯時就要確定擴展的功能 , 是靜態的 ;
③ 裝飾者模式動態擴展 : 裝飾者模式可以動態擴展功能 , 可以在代碼運行時擴展功能 ;
V . 裝飾者模式相關設計模式
1 . 裝飾者模式與代理模式 :
① 注重點 : 裝飾者模式注重動態擴展功能 ; 代理模式注重對對象訪問的控制 , 代理類對用戶隱藏具體細節 ;
② 實例對象的使用 : 裝飾者模式將原始對象作為參數傳遞給裝飾者類構造器 ; 代理模式中在代理類中創建實例對象 ;
2 . 裝飾者模式與適配器模式 : 二者都是包裝模式 ;
① 裝飾者模式 : 裝飾者模式中 , 裝飾者和被裝飾這實現相同的接口 , 或裝飾者是被裝飾者的子類 ;
② 適配器模式 : 適配器模式中 , 適配器和被適配的類有不同的接口 , 可能有部分接口重合 ;
VI . 裝飾者模式四個相關類
裝飾者模式四個相關類 :
① 抽象的 被裝飾者類 : 這是核心 , 后面的三個類都需要繼承該類 ;
② 實體的被裝飾者類 : 定義裝飾者模式時 , 用不到 , 在客戶端被用戶調用時 , 才初始化 ;
③ 抽象的裝飾者類 : 所有裝飾者類的父類 , 需要繼承抽象的被裝飾者類 ; ( 該類可選配 , 不是必須 )
④ 實體的裝飾者類 : 繼承 抽象的裝飾者類 , 在該類中維護一個 抽象裝飾者類對象 , 通過構造函數傳入實體的被裝飾者類 , 其實現的 抽象的裝飾者類 方法中 , 需要調用傳入的實體對象的對應方法 , 然后加入額外的操作 ;
VII . 裝飾者模式實體裝飾者類運行機制
實體的裝飾者類運行機制 :
① 核心 : 核心是 抽象的 被裝飾者類 類型 ,
② 裝飾者類型 : 實體的裝飾者類是 抽象的 被裝飾者類 類型的 ,
③ 裝飾者中維護的變量類型 : 其中維護的實例成員變量也是 抽象的 被裝飾者類 類型的 ,
④ 裝飾者模式運行 : 裝飾者模式使用時 , 先創建一個 抽象的 被裝飾者類 實例對象 , 創建一個裝飾者對象 , 通過構造函數將上面的實例對象傳入 , 整個裝飾者模式就是為該實例對象進行擴展的 ;
⑤ 裝飾可循環嵌套 : 實體的被裝飾類類型是 抽象的 被裝飾者類 類型的 , 其被裝飾后 , 還是 抽象的 被裝飾者類 類型的 , 然后還可以再次裝飾 , 實體的被裝飾類的動態功能的擴展 , 可以被無限裝飾擴展 ;
VIII . 裝飾者模式定義使用流程 ( 重點 )
1 . 定義抽象被裝飾者 : 定義 抽象的 被裝飾者類 , 將其要擴展的方法定義成抽象方法 ;
2 . 定義 ( 抽象的 ) 裝飾者類 :
① 繼承 抽象的 被裝飾者類 : 裝飾者類 繼承 抽象的 被裝飾者類 ;
② 維護 抽象的 被裝飾者類 成員 : 在該類中維護一個 抽象的 被裝飾者類 對象 , 該對象通過構造函數傳入 ;
③ 實現抽象方法委托 : 裝飾者類中的抽象方法 , 需要委托給類中維護的 抽象的 被裝飾者類 對象 , 在實現的該抽象方法中 , 調用上面對象的對應方法 , 然后加上要擴展的代碼 , 這些擴展的代碼 , 就是裝飾者模式位該對象動態擴展的功能 ;
3 . 定義實體對象 : 該對象是 抽象的 被裝飾者類 類型的 , 是具體的實體功能 , 要實現實際的大塊代碼邏輯 , 所有的操作 , 裝飾 , 都基于該實體對象類 ;
上面的裝飾者類 只關心被裝飾的方法 , 不定義其它內容 ;
4 . 使用裝飾者模式 :
① 創建 抽象的 被裝飾者類 實體對象 ;
② 裝飾實體對象類 : 創建 抽象的 被裝飾者類 類型的裝飾者類 , 在構造函數中 , 傳入 ① 中創建的 抽象的 被裝飾者類 類型的 實體對象 ;
③ 再次裝飾實體對象類 : 再次創建 抽象的 被裝飾者類 類型的裝飾者類 , 在構造函數中 , 傳入 ② 中創建的 抽象的 被裝飾者類 類型的 裝飾者實體對象 , 這樣就實現了二次裝飾 ;
使用的對象類型是 抽象的 被裝飾者類 , 被裝飾的對象 , 傳入裝飾者類 , 相當于包裝了一層 , 其對象類型還是 抽象的 被裝飾者類 , 這個包裝裝飾可以循環嵌套 ;
IX . 裝飾者模式 案例
1 . 案例需求 :
① 實體類對象 : 剛入學的學生 , 默認學習大學公共課 ,
② 裝飾類對象 : 如果是計算機專業的學生 , 還要繼續學習計算機專業課程 ,
③ 裝飾類對象 : 如果是音樂專業的學生 , 需要繼續學習音樂專業課程 ,
④ 二次裝飾類對象 : 如果是先學習計算機 , 然后專修音樂 , 那么需要先學習計算機專業課程 , 然后學習音樂專業課程 ;
2 . 抽象的 被裝飾者類 : 抽象的學生類 , 后面的計算機專業學生裝飾者 , 音樂專業學生裝飾者都繼承該類 ;
package kim.hsl.design.decorator;/*** 裝飾者* 抽象的裝飾者* 該類也繼承 被裝飾者 的抽象類*/ public abstract class AbstractDecorator extends AbstractStudent {//聲明抽象的被裝飾者, 通過構造器將其類型 ( 或子類類型 ) 對象傳入 , 注入實體類private AbstractStudent abstractStudent;public AbstractDecorator(AbstractStudent abstractStudent) {this.abstractStudent = abstractStudent;}/*調用實現的兩個 抽象裝飾者 方法實際上委托給了注入的 抽象裝飾者 類型的對象執行的抽象裝飾者 類型的對象是其子類對象*/@Overrideprotected String studyCourses() {return this.abstractStudent.studyCourses();} }3 . 剛入學的學生類 : 這是最普通的實體 , 是被裝飾的實體類 , 一切裝飾都是圍繞著該實體來的 ;
package kim.hsl.design.decorator;/*** 被裝飾對象* 確定的實體類*/ public class Student extends AbstractStudent {@Overrideprotected String studyCourses() {return "學習大學公共課";} }4 . 抽象的被裝飾者類 : 該類也是 抽象的被裝飾者 類 AbstractStudent 的子類 , 該類中維護了 AbstractStudent 類型的成員變量 , 通過構造函數初始化 ; 其 studyCourses 方法需要委托給 abstractStudent 成員變量的 abstractStudent 方法 ;
package kim.hsl.design.decorator;/*** 裝飾者* 抽象的裝飾者* 該類也繼承 被裝飾者 的抽象類*/ public abstract class AbstractDecorator extends AbstractStudent {//聲明抽象的被裝飾者, 通過構造器將其類型 ( 或子類類型 ) 對象傳入 , 注入實體類private AbstractStudent abstractStudent;public AbstractDecorator(AbstractStudent abstractStudent) {this.abstractStudent = abstractStudent;}/*調用實現的兩個 抽象裝飾者 方法實際上委托給了注入的 抽象裝飾者 類型的對象執行的抽象裝飾者 類型的對象是其子類對象*/@Overrideprotected String studyCourses() {return this.abstractStudent.studyCourses();} }5 . 計算機專業學生裝飾者類 : 傳入 AbstractStudent 成員變量 , studyCourses 方法中 , 在學習公共課基礎上 ( 委托成員變量 ) , 還學習 計算機專業課程 ;
package kim.hsl.design.decorator;/*** 實體裝飾者類* 必須實現其帶參數的構造器*/ public class ComputerStudentDecorator extends AbstractDecorator {public ComputerStudentDecorator(AbstractStudent abstractStudent) {super(abstractStudent);}@Overrideprotected String studyCourses() {return super.studyCourses() + " , 學習計算機專業課程";} }6 . 音樂專業學生裝飾者類 :
package kim.hsl.design.decorator;public class MusicStudentDecorator extends AbstractDecorator {public MusicStudentDecorator(AbstractStudent abstractStudent) {super(abstractStudent);}@Overrideprotected String studyCourses() {return super.studyCourses() + " , 學習音樂專業課程";} }7 . 測試裝飾者模式 : 其中測試了沒有裝飾的實體類 , 將其裝飾成計算機專業學生 , 將其裝飾成音樂專業學生 , 將其裝飾成計算機轉音樂專業的學生 ;
package kim.hsl.design.decorator;public class Main {public static void main(String[] args) {//剛入學的學生Student student = new Student();System.out.println(student.studyCourses());//大二學習計算機專業課程AbstractStudent computerStudent = new ComputerStudentDecorator(student);System.out.println(computerStudent.studyCourses());//大二學習音樂專業課程AbstractStudent musicStudent = new MusicStudentDecorator(student);System.out.println(musicStudent.studyCourses());//先學計算機 , 專修音樂的學生AbstractStudent computerMusicStudent = new ComputerStudentDecorator(computerStudent);System.out.println(computerMusicStudent.studyCourses());} }總結
以上是生活随笔為你收集整理的【设计模式】装饰者模式 ( 概念 | 适用场景 | 优缺点 | 与继承对比 | 定义流程 | 运行机制 | 案例分析 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【设计模式】外观模式 ( 概念 | 适用
- 下一篇: 【设计模式】适配器模式 ( 概念 | 适