Java設(shè)計(jì)模式中裝飾者模式應(yīng)用詳解
編程是一門藝術(shù),大批量的改動(dòng)顯然是非常丑陋的做法,用心的琢磨寫的代碼讓它變的更美觀。
在現(xiàn)實(shí)生活中,常常需要對現(xiàn)有產(chǎn)品增加新的功能或美化其外觀,如房子裝修、相片加相框等,都是裝飾器模式。
在軟件開發(fā)過程中,有時(shí)想用一些現(xiàn)存的組件。這些組件可能只是完成了一些核心功能。但在不改變其結(jié)構(gòu)的情況下,可以動(dòng)態(tài)地?cái)U(kuò)展其功能。所有這些都可以釆用裝飾器模式來實(shí)現(xiàn)。
1.裝飾器模式(Decorator)的定義
裝飾器模式:是指在不改變現(xiàn)有對象結(jié)構(gòu)的情況下,動(dòng)態(tài)地給該對象增加一些職責(zé)(即增加其額外功能)的模式,它屬于對象結(jié)構(gòu)型模式。
2.裝飾者設(shè)計(jì)模式的優(yōu)點(diǎn)與不足
裝飾者設(shè)計(jì)模式優(yōu)點(diǎn):
- 裝飾器是繼承的有力補(bǔ)充,比繼承靈活,在不改變原有對象的情況下,動(dòng)態(tài)的給一個(gè)對象擴(kuò)展功能,即插即用
- 通過使用不用裝飾類及這些裝飾類的排列組合,可以實(shí)現(xiàn)不同效果
- 裝飾器模式完全遵守開閉原則
其主要缺點(diǎn)是:裝飾器模式會(huì)增加許多子類,過度使用會(huì)增加程序得復(fù)雜性。
3.裝飾器模式的實(shí)現(xiàn)思路
通常情況下,擴(kuò)展一個(gè)類的功能會(huì)使用繼承方式來實(shí)現(xiàn)。但繼承具有靜態(tài)特征,耦合度高,并且隨著擴(kuò)展功能的增多,子類會(huì)很膨脹。如果使用組合關(guān)系來創(chuàng)建一個(gè)包裝對象(即裝飾對象)來包裹真實(shí)對象,并在保持真實(shí)對象的類結(jié)構(gòu)不變的前提下,為其提供額外的功能,這就是裝飾器模式的目標(biāo)。
4.裝飾者代碼示例
實(shí)例場景介紹:采摘水果,然后進(jìn)行包裝,這是主流程,然后需要對包裝進(jìn)行功能增強(qiáng),比如:增加防偽標(biāo)識、長途加固、標(biāo)記加急。
/** * 包裝接口 */ public interface Bag { void pack(); } /** * 這個(gè)是裝飾者的基類 */ public abstract class BagDecorator implements Bag { /** * 維持一個(gè)對 抽象構(gòu)件對象的引用 * 這個(gè)是想要增強(qiáng)的功能對象 將想要增強(qiáng)的功能對象傳進(jìn)來,然后才能進(jìn)行功能增強(qiáng) */ private Bag bag; /** * 注入一個(gè)抽象構(gòu)件類型的對象 * 將之前的對象傳遞進(jìn)來,進(jìn)行功能增強(qiáng) * @param bag */ public BagDecorator(Bag bag) { this.bag = bag; } @Override public void pack() { bag.pack(); } } /** * 增加防偽標(biāo)識 */ public class CheckedBagDecorator extends BagDecorator{ public CheckedBagDecorator(Bag bag) { super(bag); } @Override public void pack() { super.pack(); checked(); } public void checked() { System.out.println("打印上防偽標(biāo)識"); } } /** * 加固增強(qiáng) */ public class ReinforceBagDecorator extends BagDecorator { public ReinforceBagDecorator(Bag bag) { super(bag); } public void pack() { super.pack(); reinforce(); } public void reinforce() { System.out.println("加固了包裝"); } } /** * 加急功能增強(qiáng) */ public class SpeedDecorator extends BagDecorator { public SpeedDecorator(Bag bag) { super(bag); } @Override public void pack() { super.pack(); speedy(); } public void speedy() { System.out.println("打上加急標(biāo)識"); } } public static void main(String[] args){ AbstractFactory factory = new AppleFactory(); /*得到水果*/ Fruit fruit = factory.getFruit(); fruit.draw(); /*得到包裝*/ Bag bag = factory.getBag(); /*下面是對包裝進(jìn)行裝飾的過程(也就是功能增強(qiáng)的過程)*/ /*現(xiàn)需要增加防偽標(biāo)識*/ bag = new CheckedBagDecorator(bag); /*加固功能*/ bag = new ReinforceBagDecorator(bag); /*加急功能*/ bag = new SpeedDecorator(bag); bag.pack(); }
BagDecorator:功能增強(qiáng)基類,實(shí)現(xiàn)了待增強(qiáng)功能的行為接口,并持有一個(gè)包裝接口成員變量,這個(gè)變量通過構(gòu)造方法注入進(jìn)來,這個(gè)成員變量就是上一個(gè)增強(qiáng)之后的結(jié)果,一定要在上一個(gè)增強(qiáng)的結(jié)果之上進(jìn)行功能增強(qiáng),否則,就將之前的功能丟失了,所以這個(gè)成員變量很關(guān)鍵。
還有就是每次進(jìn)行包裝pack的時(shí)候,一定要先調(diào)用super方法,先之前之前的包裝,然后再進(jìn)行增強(qiáng)。
5.裝飾器模式的應(yīng)用場景
裝飾器模式通常在以下幾種情況使用:
- 當(dāng)需要給一個(gè)現(xiàn)有類添加附加職責(zé),而又不能采用生成子類的方法進(jìn)行擴(kuò)充時(shí)。例如,該類被隱藏或者該類是終極類或者采用繼承方式會(huì)產(chǎn)生大量的子類。
- 當(dāng)需要通過對現(xiàn)有的一組基本功能進(jìn)行排列組合而產(chǎn)生非常多的功能時(shí),采用繼承關(guān)系很難實(shí)現(xiàn),而采用裝飾器模式卻很好實(shí)現(xiàn)。
- 當(dāng)對象的功能要求可以動(dòng)態(tài)地添加,也可以再動(dòng)態(tài)地撤銷時(shí)。
裝飾者設(shè)計(jì)模式,在Java中非常經(jīng)典的例子是:
InputStream 的子類 FilterInputStream,OutputStream 的子類 FilterOutputStream,Reader 的子類 BufferedReader 以及 FilterReader,還有 Writer 的子類 BufferedWriter、FilterWriter 以及 PrintWriter 等,它們都是抽象裝飾類。
到此這篇關(guān)于Java設(shè)計(jì)模式中裝飾者模式應(yīng)用詳解的文章就介紹到這了,更多相關(guān)Java裝飾者模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
實(shí)踐講解SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式
本篇講解了SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式,通過實(shí)踐的方式更通俗易懂,對此不了解的同學(xué)跟著小編往下看吧2021-09-09Java數(shù)據(jù)結(jié)構(gòu)之對象的比較
比較對象是面向?qū)ο缶幊陶Z言的一個(gè)基本特征,下面這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之對象的比較,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02java8 stream 由一個(gè)list轉(zhuǎn)化成另一個(gè)list案例
這篇文章主要介紹了java8 stream 由一個(gè)list轉(zhuǎn)化成另一個(gè)list案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08基于Redis分布式鎖Redisson及SpringBoot集成Redisson
這篇文章主要介紹了基于Redis分布式鎖Redisson及SpringBoot集成Redisson,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小小伙伴可以參考一下2022-09-09SpringBoot+JWT實(shí)現(xiàn)單點(diǎn)登錄完美解決方案
單點(diǎn)登錄是一種統(tǒng)一認(rèn)證和授權(quán)機(jī)制,指在多個(gè)應(yīng)用系統(tǒng)中,用戶只需要登錄一次就可以訪問所有相互信任的系統(tǒng),不需要重新登錄驗(yàn)證,這篇文章主要介紹了SpringBoot+JWT實(shí)現(xiàn)單點(diǎn)登錄解決方案,需要的朋友可以參考下2023-07-07SpringBoot實(shí)現(xiàn)連接nacos并支持多環(huán)境部署
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)連接nacos并支持多環(huán)境部署方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06Presto自定義函數(shù)@SqlNullable引發(fā)問題詳解
這篇文章主要為大家介紹了Presto自定義函數(shù)@SqlNullable引發(fā)問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Java基于外觀模式實(shí)現(xiàn)美食天下食譜功能實(shí)例詳解
這篇文章主要介紹了Java基于外觀模式實(shí)現(xiàn)美食天下食譜功能,較為詳細(xì)的講述了外觀模式的概念、原理并結(jié)合實(shí)例形似詳細(xì)分析了Java基于外觀模式實(shí)現(xiàn)美食天下食譜功能的具體操作步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下2018-05-05