摘要:相關設計模式裝飾者模式和代理模式裝飾者模式關注再一個對象上動態添加方法代理模式關注再對代理對象的控制訪問,可以對客戶隱藏被代理類的信息裝飾著模式和適配器模式都叫包裝模式關于新職責適配器也可以在轉換時增加新的職責,但主要目的不在此。
0x01.定義與類型
定義:裝飾模式指的是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。
特點:
裝飾對象和真實對象有相同的接口。這樣客戶端對象就能以和真實對象相同的方式和裝飾對象交互。
裝飾對象包含一個真實對象的引用(reference)
裝飾對象接受所有來自客戶端的請求。它把這些請求轉發給真實的對象。
裝飾對象可以在轉發這些請求以前或以后增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。在面向對象的設計中,通常是通過繼承來實現對給定類的功能擴展。
類型:結構型
UML類圖
樣例實現
/** * 組件類接口 */ public interface IComponent { void operation(); } /** * 具體組件類的具體業務邏輯實現 */ public class Component implements IComponent { @Override public void operation() { System.out.println("component operation!"); } } /** * 裝飾器的抽象類 */ public abstract class ADecorator implements IComponent { /** * 關鍵在于這個組合組件接口對象 */ private IComponent component; public ADecorator(IComponent component) { this.component = component; } @Override public void operation () { component.operation(); } } /** * 裝飾器具體實現1 */ public class Decorator1 extends ADecorator { public Decorator1(IComponent component) { super(component); } @Override public void operation() { super.operation(); System.out.println("decorator1"); } } /** * 裝飾器具體實現2 */ public class Decorator2 extends ADecorator { public Decorator2(IComponent component) { super(component); } @Override public void operation() { super.operation(); System.out.println("decorator2"); } }
測試與應用類
/** * 應用與測試類 */ public class Test { public static void main(String[] args) { //應用類 IComponent component; //初始化 component = new Component(); //裝飾 component = new Decorator1(component); component = new Decorator2(component); //具體方法的調用 component.operation(); } }
輸出結果
component operation! decorator1 decorator2
裝飾著模式中的各組件:
抽象構件(IComponent)角色:給出一個抽象接口,以規范準備接收附加責任的對象。
具體構件(Component)角色:定義一個將要接收附加責任的類。
裝飾(ADecorator)角色:持有一個構件(IComponent)對象的實例,并定義一個與抽象構件接口一致的接口。
具體裝飾(Decorator1/Decorator2)角色:負責給構件對象“貼上”附加的責任。
0x02.使用場景需要擴展一個類的功能,或給一個類添加附加職責。
需要動態的給一個對象添加功能,這些功能可以再動態的撤銷。
需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關系變的不現實。
當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
0x03.優點Decorator模式與繼承關系的目的都是要擴展對象的功能,但是Decorator可以提供比繼承更多的靈活性。
通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合。
符合開閉原則
0x04.缺點這種比繼承更加靈活機動的特性,也同時意味著更加多的復雜性。
裝飾模式會導致設計中出現許多小類,如果過度使用,會使程序變得很復雜。
裝飾模式是針對抽象組件(Component)類型編程。但是,如果你要針對具體組件編程時,就應該重新思考你的應用架構,以及裝飾者是否合適。當然也可以改變Component接口,增加新的公開的行為,實現“半透明”的裝飾者模式。在實際項目中要做出最佳選擇
0x05.舉例實現裝飾著模式我們買煎餅果子可以選擇加香腸,還是加雞蛋。煎餅果子就是我們的組件類,而加雞蛋加培根則是裝飾者的具體實現類.
裝飾者模式Java實現
/** * 煎餅的抽象類,也就是組建類 */ public abstract class ABattercake { /** * 最后的描述 * @return */ protected abstract String getDesc (); /** * 總共的價格 * @return */ protected abstract int cost (); } /** * 煎餅的具體實現 */ public class Battercake extends ABattercake { @Override protected String getDesc() { return "煎餅"; } @Override protected int cost() { return 8; } } /** * 裝飾著的抽象類 */ public abstract class AbstractDecorator extends ABattercake { //組合的煎餅對象 private ABattercake aBattercake; public AbstractDecorator(ABattercake aBattercake) { this.aBattercake = aBattercake; } protected abstract void doSomething(); @Override protected String getDesc() { return aBattercake.getDesc(); } @Override protected int cost() { return aBattercake.cost(); } } /** * 裝飾者的具體實現 */ public class EggDecorator extends AbstractDecorator { public EggDecorator(ABattercake aBattercake) { super(aBattercake); } @Override protected void doSomething() { } @Override protected String getDesc() { return super.getDesc() + " 加一個雞蛋"; } @Override protected int cost() { return super.cost() + 1; } } /** * 裝飾者的具體實現 */ public class SausageDecorator extends AbstractDecorator { public SausageDecorator(ABattercake aBattercake) { super(aBattercake); } @Override protected void doSomething() { } @Override protected String getDesc() { return super.getDesc() + " 加一根香腸"; } @Override protected int cost() { return super.cost() + 2; } }
應用的測試類
public class Test { public static void main(String[] args) { ABattercake aBattercake; aBattercake = new Battercake(); aBattercake = new EggDecorator(aBattercake); aBattercake = new EggDecorator(aBattercake); aBattercake = new SausageDecorator(aBattercake); System.out.println(aBattercake.getDesc() + "銷售價格:" + aBattercake.cost()); } }
輸入結果
煎餅 加一個雞蛋 加一個雞蛋 加一根香腸銷售價格:12
樣例UML類圖
注意:裝飾者最上層的類是否使用抽象類,這個是看業務的。
0x06.相關設計模式
裝飾者模式和代理模式
裝飾者模式:關注再一個對象上動態添加方法
代理模式:關注再對代理對象的控制訪問,可以對客戶隱藏被代理類的信息
裝飾著模式和適配器模式
都叫包裝模式
關于新職責:適配器也可以在轉換時增加新的職責,但主要目的不在此。裝飾者模式主要是給被裝飾者增加新職責的。
關于原接口:適配器模式是用新接口來調用原接口,原接口對新系統是不可見或者說不可用的。裝飾者模式原封不動的使用原接口,系統對裝飾的對象也通過原接口來完成使用。(增加新接口的裝飾者模式可以認為是其變種--“半透明”裝飾者)
關于其包裹的對象:適配器是知道被適配者的詳細情況的(就是那個類或那個接口)。裝飾者只知道其接口是什么,至于其具體類型(是基類還是其他派生類)只有在運行期間才知道。
0x07.源碼中的裝飾者BufferedReader
BufferInputStream/BufferOutputStream
Spring. TransactionAwareCacheDecorator
Mybatis. Cache
0x08.源碼設計模式之裝飾著模式: https://github.com/sigmako/design-pattern/tree/master/decorator
0x09.參考慕課網設計模式精講: https://coding.imooc.com/class/270.html
《JAVA與模式》之裝飾模式: https://www.cnblogs.com/java-my-life/archive/2012/04/20/2455726.html
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75335.html
摘要:裝飾者模式組成結構抽象構件給出抽象接口或抽象類,以規范準備接收附加功能的對象。裝飾者模式圖解裝飾者模式應用場景需要擴展一個類的功能,或給一個類添加附加職責。裝飾者對象接受所有來自客戶端的請求。參考資料設計模式 一、了解裝飾者模式 1.1 什么是裝飾者模式 裝飾者模式指的是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾者來包裹真實的對...
摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式原文地址是每天一個設計模式之裝飾者模式歡迎關注個人技術博客。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式...
摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式原文地址是每天一個設計模式之裝飾者模式歡迎關注個人技術博客。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式...
摘要:什么是裝飾者模式今天我們來講另外一個非常實用的設計模式裝飾者模式。就增加功能來說,裝飾者模式相比生成子類更為靈活。下面,裝飾者模式就要正式登場了。下一步,我們可以愉快的去使用裝飾者模式啦 什么是裝飾者模式 今天我們來講另外一個非常實用的設計模式:裝飾者模式。這個名字聽上去有些莫名其妙,不著急,我們先來記住它的一個別名:包裝器模式。 我們記著這兩個名字來開始今天的文章。 首先還是上《設計...
摘要:概念裝飾模式顧名思義,裝飾模式是一種對對象數據的多次過濾,就像裝飾一樣,一層層的修飾,獲取滿意的結果。實現裝飾者裝飾操作這是個洗菜操作??偨Y當我們需要對數據進行過濾的時候,裝飾模式可以成為你的選擇 概念: 裝飾模式: 顧名思義,裝飾模式是一種對對象數據的多次過濾,就像裝飾一樣, 一層層的修飾, 獲取滿意的結果。 裝飾模式共分為兩個部分: 1: 裝飾者: 在這個接口接口下面的類和方法用...
閱讀 631·2021-08-17 10:15
閱讀 1715·2021-07-30 14:57
閱讀 1970·2019-08-30 15:55
閱讀 2813·2019-08-30 15:55
閱讀 2703·2019-08-30 15:44
閱讀 662·2019-08-30 14:13
閱讀 2380·2019-08-30 13:55
閱讀 2587·2019-08-26 13:56