【设计模式】结构型模式——装饰模式
文章目錄
- 一、定義
- 二、問題
- 三、解決方案
- 四、實現(xiàn)
- 五、UML圖
- 六、裝飾模式應(yīng)用場景
- 七、總結(jié)
- 優(yōu)點
- 缺點
- 八、與其他模式的關(guān)系
一、定義
裝飾模式是一種結(jié)構(gòu)型設(shè)計模式, 允許你通過將對象放入包含行為的特殊封裝對象中來為原對象綁定新的行為。
二、問題
假設(shè)你的公司要發(fā)獎金,一個人有基礎(chǔ)獎金,而有的人還有業(yè)務(wù)增長獎金,個人進步獎金,更高層的人(比如 經(jīng)理)除了有個人的獎金外,還有團隊累計獎金,團隊增長獎金 等等。
如果我們使用一個子類來分發(fā)這些獎金,那么我們子類的組合會很多很多。
那么我真的要設(shè)計這么多類嗎?
三、解決方案
裝飾模式就很好的解決了這一點:
我們可以將簡單的發(fā)獎金行為放在基礎(chǔ)裝飾類中, 但將所有其他獎金方法放入裝飾中。
客戶端代碼必須將基礎(chǔ)裝飾類放入一系列自己所需的裝飾中。 因此最后的對象將形成一個棧結(jié)構(gòu)。
實際與客戶端進行交互的對象將是最后一個進入棧中的裝飾對象(即具體部件)。
四、實現(xiàn)
1、部件 Component
發(fā)放獎金接口
聲明封裝器和被封裝對象的公用接口。
2、具體部件 Concrete Component
具體部件 (Concrete Component) 類是被封裝對象所屬的類。 它定義了基礎(chǔ)行為, 但裝飾類可以改變這些行為。
(1) 普通職工
(2)、經(jīng)理
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("經(jīng)理"+this.name+"基礎(chǔ)工資為"+10000d);} }3、基礎(chǔ)裝飾類(BaseDecorator)
基礎(chǔ)裝飾 (Base Decorator) 類擁有一個指向被封裝對象的引用成員變量。 該變量的類型應(yīng)當(dāng)被聲明為通用部件接口, 這樣它就可以引用具體的部件和裝飾。 裝飾基類會將所有操作委派給被封裝的對象(具體部件)。
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) 定義了可動態(tài)添加到部件的額外行為。 具體裝飾類會重寫裝飾基類的方法, 并在調(diào)用父類方法之前或之后進行額外的行為。
(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) 可以使用多層裝飾來封裝部件, 只要它能使用通用接口與所有對象互動即可。
運行展示:(普通職工小王)
即 基礎(chǔ)裝飾類的reward變量 是 SelfIncrease……,而 Seflncrease……的reward變量 是 SelfAccmu……,而SelfAccmu……的reward變量是Staff。
調(diào)用方法工資方法時,先調(diào)用的是基礎(chǔ)裝飾類的sentReward方法,而基礎(chǔ)裝飾類的sentReward方法是 用reward變量 調(diào)用sentReward方法,而reward變量又是SelfIncrease……所以 調(diào)用SelfIncrease……的sentReward方法,調(diào)用SelfIncrease……的sentReward方法,先調(diào)用父類的sentReward方法,父類中的reward變量而是 SelfAccmu……,所以調(diào)用SelfAccumu……的sentReward方法………………依此類推,其實就是一個遞歸調(diào)用。
debug 自己看看吧
五、UML圖
六、裝飾模式應(yīng)用場景
- 在無需修改代碼的情況下即可使用對象, 且希望在運行時為對象新增額外的行為, 可以使用裝飾模式
- 用繼承來擴展對象行為的方案難以實現(xiàn)或者根本不可行, 你可以使用該模式。
七、總結(jié)
優(yōu)點
- 你無需創(chuàng)建新子類即可擴展對象的行為。
- 你可以在運行時添加或刪除對象的功能。
- 你可以用多個裝飾封裝對象來組合幾種行為。
- 單一職責(zé)原則。 你可以將實現(xiàn)了許多不同行為的一個大類拆分為多個較小的類。
缺點
- 在封裝器棧中刪除特定封裝器比較困難。
- 實現(xiàn)行為不受裝飾棧順序影響的裝飾比較困難。
- 各層的初始化配置代碼看上去可能會很糟糕
八、與其他模式的關(guān)系
- 與策略模式
裝飾模式可讓你更改對象的外表, 策略模式則讓你能夠改變其本質(zhì)。
裝飾模式是遞歸調(diào)用,策略模式是一次調(diào)用。
總結(jié)
以上是生活随笔為你收集整理的【设计模式】结构型模式——装饰模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 论文阅读笔记之《Learning Dee
- 下一篇: 设计模式 - 装饰模式