设计模式:装饰模式(Decorator)
生活随笔
收集整理的這篇文章主要介紹了
设计模式:装饰模式(Decorator)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
動態(tài)地給一個對象添加一些額外的職責(zé)。就增加功能來說,裝飾模式想必生成子類更為靈活。裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關(guān)系的一個替代方案。裝飾模式中的角色有:1. 抽象構(gòu)件角色(Component):給出一個抽象接口,以規(guī)范準(zhǔn)備接受附加責(zé)任的對象。2. 具體構(gòu)件角色(ConcreteComponent):定義一個將要接收附加責(zé)任的類。3. 裝飾角色(Decorator):持有一個構(gòu)件(Component)對象的實例,并定義一個與抽象構(gòu)件接口一致的接口。4. 具體裝飾角色(ConcreteDecorator):負(fù)責(zé)給構(gòu)件對象“貼上”附加的責(zé)任。舉個簡單例子(類比《Head Fisrt》中的星巴克:吃雜糧煎餅,加個雞蛋,加根火腿,加份辣條)
1 抽象構(gòu)件角色import java.math.BigDecimal;public abstract class Pancake {protected String name;public String getName() {return this.name;}public abstract BigDecimal getPrice();}
2 具體構(gòu)件角色public class CoarsePancake extends Pancake {public CoarsePancake() {this.name = "雜糧煎餅";}@Overridepublic BigDecimal getPrice() {return new BigDecimal(5);}}
3 裝飾角色public abstract class Condiment extends Pancake {public abstract String getName();public void sold() {System.out.println(getName() + ": " + getPrice());}}
4 具體裝飾角色public class Egg extends Condiment {private Pancake pancake;public Egg(Pancake pancake) {this.pancake = pancake;}@Overridepublic String getName() {return pancake.getName() + ", 加雞蛋";}@Overridepublic BigDecimal getPrice() {return pancake.getPrice().add(new BigDecimal(1.5));}}public class Ham extends Condiment {private Pancake pancake;public Ham(Pancake pancake) {this.pancake = pancake;}@Overridepublic String getName() {return this.pancake.getName() + ", 加火腿";}@Overridepublic BigDecimal getPrice() {return pancake.getPrice().add(new BigDecimal(2));}}public class Lettuce extends Condiment {private Pancake pancake;public Lettuce(Pancake pancake) {this.pancake = pancake;}@Overridepublic String getName() {return this.pancake.getName() + ", 加生菜";}@Overridepublic BigDecimal getPrice() {return pancake.getPrice().add(new BigDecimal(1));}}
5 測試代碼public class MainTest {public static void main(String[] args) {Pancake pancake = new CoarsePancake();Condiment egg = new Egg(pancake);Condiment ham = new Ham(egg);ham.sold();Condiment lettuce = new Lettuce(ham);lettuce.sold();}}
測試結(jié)果:雜糧煎餅, 加雞蛋, 加火腿: 8.5
雜糧煎餅, 加雞蛋, 加火腿, 加生菜: 9.5
適用場景1. 想透明并且動態(tài)地給對象增加新的職責(zé)的時候2. 給對象增加的職責(zé),在未來存在增加或減少功能3. 用繼承擴展功能不太現(xiàn)實的情況下,應(yīng)該考慮用組合的方式
優(yōu)點:1. 通過組合而非繼承的方式,實現(xiàn)了動態(tài)擴展對象的功能的能力。2. 有效避免了使用繼承的方式擴展對象功能而帶來的靈活性差,子類無限制擴張的問題。3. 充分利用了繼承和組合的長處和短處,在靈活性和擴展性之間找到完美的平衡點。4. 裝飾者和被裝飾者之間雖然都是同一類型,但是它們彼此是完全獨立并可以各自獨立任意改變的。5. 遵守大部分GRAP原則和常用設(shè)計原則,高內(nèi)聚、低偶合。
缺點:1. 裝飾鏈不能過長,否則會影響效率。2. 因為所有對象都是繼承于Component,所以如果Component內(nèi)部結(jié)構(gòu)發(fā)生改變,則不可避免地影響所有子類(裝飾者和被裝飾者),3. 只在必要的時候使用裝飾者模式,否則會提高程序的復(fù)雜性,增加系統(tǒng)維護難度。
Jdk中的裝飾模式:由于Java I/O庫需要很多性能的各種組合,如果這些性能都是用繼承的方法實現(xiàn)的,那么每一種組合都需要一個類,這樣就會造成大量性能重復(fù)的類出現(xiàn)。而如果采用裝飾模式,那么類的數(shù)目就會大大減少,性能的重復(fù)也可以減至最少。因此裝飾模式是Java I/O庫的基本模式。
根據(jù)上圖可以看出:1. 抽象構(gòu)件(Component)角色:由InputStream扮演。這是一個抽象類,為各種子類型提供統(tǒng)一的接口。2. 具體構(gòu)件(ConcreteComponent)角色:由ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream等類扮演。它們實現(xiàn)了抽象構(gòu)件角色所規(guī)定的接口。3. 抽象裝飾(Decorator)角色:由FilterInputStream扮演。它實現(xiàn)了InputStream所規(guī)定的接口。4. 具體裝飾(ConcreteDecorator)角色:由幾個類扮演,分別是BufferedInputStream、DataInputStream以及兩個不常用到的類LineNumberInputStream、PushbackInputStream。
?
總結(jié)
以上是生活随笔為你收集整理的设计模式:装饰模式(Decorator)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ActiveMQ的几种集群配置
- 下一篇: asp.net ajax控件工具集 Au