定義:裝飾設計模式允許向一個現有的物件新增功能,而不改變其結構(這就很符合程式設計的「開閉原則」),重點突出類功能的增強,屬於結構型建立模式,這種模式建立了一個裝飾類,用來包裝原有類,保持類方法簽名完整的情況下,提供了額外的功能。
意圖:動態地給一個物件增加一些額外的職責,裝飾是比子類更為靈活和優秀的一種方案;
主要解決:通常擴充套件一個類我們通常使用繼承實現,由於繼承為類引入特徵,通常隨著功能的擴充套件,子類會很膨脹,容易造成類爆炸;裝飾設計模式是一種使用組合替代繼承的最佳實現,《effective java》中也建議「組合優先於繼承」,物件導向程式設計有封裝、繼承和多型三大特徵,其中封裝和繼承卻有一點矛盾,繼承意味著子類依賴了父類別的實現,一旦父類別中改變了規則,會對子類造成影響,這是打破封裝的一種表現,而組合就是巧用封裝來實現繼承功能的程式碼複用;
何時使用:在不想增加很多子類的情況下擴充套件類的功能;
設計模式結構圖:
模式角色分析:
1、抽象構件角色(Component):定義一個抽象介面,用來規範被裝飾類的行為;
2、具體構件角色(ConcreteComponent):需要被裝飾的目標物件;
3、抽象裝飾角色(decorator):持有一個具體構件物件的範例,並定義一個與抽象構建介面一致的介面;
4、具體裝飾角色(ConcreteDecorator):具體的裝飾類,負責給被裝飾者擴充套件功能;
優點:
1、裝飾和繼承都能達到擴充套件類功能的目的,但是裝飾模式更加靈活;
2、裝飾設計模式有很好的可延伸性;
3、通過使用不同的具體裝飾類,以及這些類的排列組合,可以實現多重灌飾;
缺點:
裝飾設計或是會導致程式設計中出現許多小物件,如果過度使用會使程式變得更加複雜;
UML類圖:
測試程式碼:
package cn.com.pep.model.decarator.impl2; /** * * @Title: Shape * @Description: 抽象構件角色(Component),用來約束被裝飾物件的行為 * @author wwh * @date 2022-9-1 16:11:29 */ public interface Shape { /** * * @Title: draw * @Description: */ public void draw(); }
package cn.com.pep.model.decarator.impl2; /** * * @Title: Circle * @Description: 具體構件角色(ConcreteComponent),被裝飾的物件 * @author wwh * @date 2022-9-1 16:14:50 */ public class Circle implements Shape { @Override public void draw() { System.err.println("Shape: Circle."); } }
package cn.com.pep.model.decarator.impl2; /** * * @Title: Rectangle 具體構件角色(ConcreteComponent),被裝飾的物件 * @Description: * @author wwh * @date 2022-9-1 16:13:36 */ public class Rectangle implements Shape { @Override public void draw() { System.err.println("Shape: Recatangle."); } }
package cn.com.pep.model.decarator.impl2; /** * * @Title: ShapeDecorator * @Description: 抽象裝飾角色(Decorator),定義一組與抽象構件角色相同的行為, * 通過實現介面來定義,並持有一個具體構件角色的參照,在完成裝飾設計模式增加的功能之後再呼叫原有功能 * @author wwh * @date 2022-9-1 16:16:42 */ public abstract class ShapeDecorator implements Shape{ private Shape shape; public ShapeDecorator(Shape shape) { this.shape = shape; } @Override public void draw() { shape.draw(); } }
package cn.com.pep.model.decarator.impl2; /** * * @Title: RedShapeDecorator * @Description: 具體的裝飾者類,負責給被裝飾者類擴充套件功能; * @author wwh * @date 2022-9-1 16:55:38 */ public class RedShapeDecorator extends ShapeDecorator{ public RedShapeDecorator(Shape shape) { super(shape); } @Override public void draw() { super.draw(); setRedColor(); } private void setRedColor() { System.err.println("Red Color!"); } }
package cn.com.pep.model.decarator.impl2; /** * * @Title: DecoratorPatternDemo * @Description: 測試類 * @author wwh * @date 2022-9-1 16:56:54 */ public class DecoratorPatternDemo { public static void main(String[] args) { Shape shape = new Rectangle(); ShapeDecorator decorator = new RedShapeDecorator(shape); decorator.draw(); } }
裝飾設計模式在JDK原始碼中的應用:
裝飾設計模式在jdk原始碼中最具代表性的應用莫過於I/O體系中的InputStream/OutputStream,Reader/Writer等,現在我們就以InputStream為例進行分析:
抽象構件角色(Component):InputStream類,用來定義具體構件的行為;
具體構件角色(ConcreteComponent):FileInputStream、ByteArrayInputStream、ObjectInputStream類,具體被裝飾的類;
抽象裝飾角色(Decorator):FilterInputStream類,通過繼承抽象構建角色類來定義一組與具體構件類相同的行為,再通過聚合的方式來持有被裝飾角色的參照;
具體裝飾角色(ConcreteDecorator):BufferedInputStream、DataInputStream、CheckedInputStream類,具體裝飾者類,負責給被裝飾者增加功能;
寫在後面:
裝飾設計模式中,裝飾者和被裝飾者都可以獨立擴充套件,沒有耦合關係,被裝飾者無需知道裝飾者的存在,裝飾者也無需關心被裝飾者的具體細節,裝飾設計模式可以動態擴充套件一個類的功能,
是繼承的一種替代方案,但是裝飾的層級過多可能比較複雜。
本文來自部落格園,作者:一隻烤鴨朝北走,僅用於技術學習,所有資源都來源於網路,部分是轉發,部分是個人總結。歡迎共同學習和轉載,轉載請在醒目位置標明原文。如有侵權,請留言告知,及時撤除。轉載請註明原文連結:https://www.cnblogs.com/wha6239/p/16646861.html