【设计模式 03】装饰模式——俄罗斯套娃?
裝飾模式(俄羅斯套娃?)
裝飾模式:動態的給某些對象添加額外的功能
參考:
-
簡書 | 裝飾模式
-
博客園 | 簡說設計模式——裝飾模式
-
博客園 | 裝飾器模式 Decorator 結構型 設計模式 (十)
什么是裝飾模式
裝飾模式也叫裝飾器模式,python中的裝飾器就是這種模式的體現,對于一個類,如果要添加一個新功能,除了修改代碼外(違反開閉原則),可以使用繼承,但通過繼承添加新功能并不適合所有場景,如
裝飾模式中的對象包括:
裝飾器(用來為被裝飾對象動態添加新功能)
抽象被裝飾對象(所有能被裝飾對象的抽象)
被裝飾對象
客戶端如果希望給某個對象動態添加一個新功能,就可以把這個對象(被裝飾對象)傳遞給裝飾器,由裝飾器實現新功能,并保存一個被裝飾對象的引用,并返回給客戶端一個裝飾器對象,這樣,被裝飾對象原來的行為和屬性并沒有改變,甚至被裝飾對象本身就沒有改變,只是在外面套了一個殼子,新功能是這個殼子提供的。就像TCP/IP協議棧中,應用層的數據包到傳輸層通過加TCP或UDP首部來傳輸一樣。
裝飾模式優缺點
優點:
缺點:
過多的裝飾類可能使程序變得很復雜
裝飾模式是針對抽象組件(Component)類型編程。但是,如果你要針對具體組件編程時,就應該重新思考你的應用架構,以及裝飾者是否合適。當然也可以改變Component接口,增加新的公開的行為,實現“半透明”的裝飾者模式。在實際項目中要做出最佳選擇。
作者:慵懶的陽光丶
適用場景
例
比如賣烤冷面,最基本的就是面(抽象被裝飾對象)具體的就是烤冷面(被裝飾對象),然后可以往面里面加各種配料(抽象裝飾器),如雞蛋,辣條等(具體裝飾器),由于不同配料的加入順序對最后的烤冷面有影響,所以如果要用繼承拓展“烤冷面”,那先加雞蛋再加辣條和先加辣條再加雞蛋就需要寫兩個子類,造成冗余重復,這種場景就適合適用裝飾模式。
抽象被裝飾對象
package pers.junebao.decorator_pattern;public abstract class Noodles {public String rawMaterial; // 配料public abstract void sayWhoAmI(); }具體的被裝飾對象:
package pers.junebao.decorator_pattern;public class BakedColdNoodles extends Noodles {BakedColdNoodles() {this.rawMaterial = "面"; // 最原始的烤冷面,配料只有面}@Overridepublic void sayWhoAmI() {System.out.println("我是普通烤冷面!");} }抽象裝飾器:
package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public abstract class Burden extends Noodles {public Noodles noodles; // 裝飾器中保留一份被裝飾對象的引用,方便客戶端使用public Burden(Noodles noodles) {this.noodles = noodles;} }- 裝飾器是為某一類對象提供裝飾的(這里就是實現了Noodles 的類)
具體的裝飾器類:
-
加雞蛋
package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public class AddEggs extends Burden {public AddEggs(Noodles noodles) {super(noodles);this.rawMaterial = noodles.rawMaterial + ", 雞蛋";}@Overridepublic void sayWhoAmI() {System.out.println("我是加了雞蛋的烤冷面!!");}} -
加辣條
package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public class AddSpicyStrips extends Burden{public AddSpicyStrips(Noodles noodles) {super(noodles);this.rawMaterial = noodles.rawMaterial + " ,辣條";}@Overridepublic void sayWhoAmI() {System.out.println("我是加了辣條的烤冷面!!");} }
客戶端:
package pers.junebao.decorator_pattern;import pers.junebao.decorator_pattern.decorator.AddEggs; import pers.junebao.decorator_pattern.decorator.AddSpicyStrips;public class Main {public static void main(String[] args) {Noodles bcn = new BakedColdNoodles();Noodles bcnAddEgg = new AddEggs(bcn);bcnAddEgg.sayWhoAmI();System.out.println(bcnAddEgg.rawMaterial);Noodles bcnEggSpicyS = new AddSpicyStrips(bcnAddEgg);bcnEggSpicyS.sayWhoAmI();System.out.println(bcnEggSpicyS.rawMaterial);} } /* 我是加了雞蛋的烤冷面!! 面, 雞蛋 我是加了辣條的烤冷面!! 面, 雞蛋 ,辣條*/這樣如果想先加辣條在家雞蛋,就可以使用AddSpicyStrips先裝飾BakedColdNoodles,再用AddEggs裝飾AddSpicyStrips。
GitHub | 完整代碼
總結
以上是生活随笔為你收集整理的【设计模式 03】装饰模式——俄罗斯套娃?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: edius隐藏快捷键_EDIUS 常用快
- 下一篇: 高职高专教材c语言,高职《C语言程序设计