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