【设计模式】结构型模式——装饰模式
文章目錄
- 一、定義
- 二、問題
- 三、解決方案
- 四、實現
- 五、UML圖
- 六、裝飾模式應用場景
- 七、總結
- 優點
- 缺點
- 八、與其他模式的關系
一、定義
裝飾模式是一種結構型設計模式, 允許你通過將對象放入包含行為的特殊封裝對象中來為原對象綁定新的行為。
二、問題
假設你的公司要發獎金,一個人有基礎獎金,而有的人還有業務增長獎金,個人進步獎金,更高層的人(比如 經理)除了有個人的獎金外,還有團隊累計獎金,團隊增長獎金 等等。
如果我們使用一個子類來分發這些獎金,那么我們子類的組合會很多很多。
那么我真的要設計這么多類嗎?
三、解決方案
裝飾模式就很好的解決了這一點:
我們可以將簡單的發獎金行為放在基礎裝飾類中, 但將所有其他獎金方法放入裝飾中。
客戶端代碼必須將基礎裝飾類放入一系列自己所需的裝飾中。 因此最后的對象將形成一個棧結構。
實際與客戶端進行交互的對象將是最后一個進入棧中的裝飾對象(即具體部件)。
四、實現
1、部件 Component
發放獎金接口
聲明封裝器和被封裝對象的公用接口。
2、具體部件 Concrete Component
具體部件 (Concrete Component) 類是被封裝對象所屬的類。 它定義了基礎行為, 但裝飾類可以改變這些行為。
(1) 普通職工
(2)、經理
package com.atmae.decorator;/*** @Author: Mae* @Date: 2022/4/2* @Time: 15:22* @Description:*/ public class Manage implements Reward{String name;public Manage(String name) {this.name=name;}@Overridepublic void sendReward() {System.out.println("經理"+this.name+"基礎工資為"+10000d);} }3、基礎裝飾類(BaseDecorator)
基礎裝飾 (Base Decorator) 類擁有一個指向被封裝對象的引用成員變量。 該變量的類型應當被聲明為通用部件接口, 這樣它就可以引用具體的部件和裝飾。 裝飾基類會將所有操作委派給被封裝的對象(具體部件)。
package com.atmae.decorator;/*** @Author: Mae* @Date: 2022/4/2* @Time: 13:04* @Description:*/ public class RewardDecorator implements Reward {private Reward reward;public RewardDecorator() {}public RewardDecorator(Reward reward) {this.reward = reward;}@Overridepublic void sendReward() {reward.sendReward();} }4、具體裝飾類 (Concrete Decorators)
具體裝飾類 (Concrete Decorators) 定義了可動態添加到部件的額外行為。 具體裝飾類會重寫裝飾基類的方法, 并在調用父類方法之前或之后進行額外的行為。
(1)、個人增長工資
(2)、個人積累工資
package com.atmae.decorator;/*** @Author: Mae* @Date: 2022/4/2* @Time: 13:56* @Description:*/ public class SelfIncreaseRewardDecorator extends RewardDecorator{public SelfIncreaseRewardDecorator(Reward reward) {super(reward);}public SelfIncreaseRewardDecorator() {}@Overridepublic void sendReward() {super.sendReward();System.out.println("\t\t個人增長工資:"+2000d);} }(3)、團隊增長工資
package com.atmae.decorator;/*** @Author: Mae* @Date: 2022/4/2* @Time: 15:37* @Description:*/ public class TeamIncreaseRewardDecorator extends RewardDecorator{public TeamIncreaseRewardDecorator() {}public TeamIncreaseRewardDecorator(Reward reward) {super(reward);}@Overridepublic void sendReward() {super.sendReward();System.out.println("\t\t團隊增長工資:"+4000d);} }(4)、團隊積累工資
package com.atmae.decorator;/*** @Author: Mae* @Date: 2022/4/2* @Time: 13:57* @Description:*/ public class TeamAccumulationRewardDecorator extends RewardDecorator{public TeamAccumulationRewardDecorator(Reward reward) {super(reward);}public TeamAccumulationRewardDecorator() {}@Overridepublic void sendReward() {super.sendReward();System.out.println("\t\t團隊積累工資:"+6000d);} }5、客戶端(Client)
客戶端 (Client) 可以使用多層裝飾來封裝部件, 只要它能使用通用接口與所有對象互動即可。
運行展示:(普通職工小王)
即 基礎裝飾類的reward變量 是 SelfIncrease……,而 Seflncrease……的reward變量 是 SelfAccmu……,而SelfAccmu……的reward變量是Staff。
調用方法工資方法時,先調用的是基礎裝飾類的sentReward方法,而基礎裝飾類的sentReward方法是 用reward變量 調用sentReward方法,而reward變量又是SelfIncrease……所以 調用SelfIncrease……的sentReward方法,調用SelfIncrease……的sentReward方法,先調用父類的sentReward方法,父類中的reward變量而是 SelfAccmu……,所以調用SelfAccumu……的sentReward方法………………依此類推,其實就是一個遞歸調用。
debug 自己看看吧
五、UML圖
六、裝飾模式應用場景
- 在無需修改代碼的情況下即可使用對象, 且希望在運行時為對象新增額外的行為, 可以使用裝飾模式
- 用繼承來擴展對象行為的方案難以實現或者根本不可行, 你可以使用該模式。
七、總結
優點
- 你無需創建新子類即可擴展對象的行為。
- 你可以在運行時添加或刪除對象的功能。
- 你可以用多個裝飾封裝對象來組合幾種行為。
- 單一職責原則。 你可以將實現了許多不同行為的一個大類拆分為多個較小的類。
缺點
- 在封裝器棧中刪除特定封裝器比較困難。
- 實現行為不受裝飾棧順序影響的裝飾比較困難。
- 各層的初始化配置代碼看上去可能會很糟糕
八、與其他模式的關系
- 與策略模式
裝飾模式可讓你更改對象的外表, 策略模式則讓你能夠改變其本質。
裝飾模式是遞歸調用,策略模式是一次調用。
總結
以上是生活随笔為你收集整理的【设计模式】结构型模式——装饰模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 论文阅读笔记之《Learning Dee
- 下一篇: 设计模式 - 装饰模式