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