23種設(shè)計(jì)模式(6)java裝飾者模式
23種設(shè)計(jì)模式第六篇:java裝飾者模式
定義:
在不必改變?cè)愇募驮愂褂玫睦^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。
它是通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是用裝飾來(lái)包裹真實(shí)的對(duì)象來(lái)實(shí)現(xiàn)。
角色:
抽象構(gòu)件角色(Project):給出一個(gè)接口,以規(guī)范準(zhǔn)備接收附加責(zé)任的對(duì)象。
具體構(gòu)件角色(Employe):定義一個(gè)將要接收附加責(zé)任的類。
裝飾角色(Manager):持有一個(gè)構(gòu)件對(duì)象的實(shí)例,并定義一個(gè)與抽象構(gòu)件接口一致的接口。
具體裝飾角色(ManagerA、ManagerB):負(fù)責(zé)給構(gòu)件對(duì)象“貼上”附加的責(zé)任。
示例:
公共接口:
public interface Person {
void eat();
}
被裝飾對(duì)象:
public class OldPerson implements Person {
@Override
public void eat() {
System.out.println("吃飯");
}
}
裝飾對(duì)象:
public class NewPerson implements Person {
private OldPerson p;
NewPerson(OldPerson p) {
this.p = p;
}
@Override
public void eat() {
System.out.println("生火");
System.out.println("做飯");
p.eat();
System.out.println("刷碗");
}
}
測(cè)試:
public class PersonDemo {
public static void main(String[] args) {
OldPerson old = new OldPerson();
//old.eat();
NewPerson np = new NewPerson(old);
np.eat();
}
}
通過(guò)例子可以看到,沒(méi)有改變?cè)瓉?lái)的OldPerson類,同時(shí)也沒(méi)有定義他的子類而實(shí)現(xiàn)了Person的擴(kuò)展,這就是裝飾者模式的作用。
優(yōu)點(diǎn):
1、使用裝飾者模式比使用繼承更加靈活,因?yàn)樗x擇通過(guò)一種動(dòng)態(tài)的方式來(lái)擴(kuò)展一個(gè)對(duì)象的功能,在運(yùn)行時(shí)可以選擇不同的裝飾器,從而實(shí)現(xiàn)不同的行為。
2、通過(guò)使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創(chuàng)造出很多不同行為的組合??梢允褂枚鄠€(gè)具體裝飾類來(lái)裝飾同一對(duì)象,得到功能更為強(qiáng)大的對(duì)象。
3、具體構(gòu)件類與具體裝飾類可以獨(dú)立變化,他能是低耦合的。用戶可以根據(jù)需要來(lái)增加新的具體構(gòu)件類和具體裝飾類,在使用時(shí)再對(duì)其進(jìn)行各種組合,原有代碼無(wú)須改變,符合“開(kāi)閉原則”。
缺點(diǎn):
1、會(huì)產(chǎn)生很多的小對(duì)象,增加了系統(tǒng)的復(fù)雜性
2、這種比繼承更加靈活機(jī)動(dòng)的特性,也同時(shí)意味著裝飾模式比繼承更加易于出錯(cuò),排錯(cuò)也很困難,對(duì)于多次裝飾的對(duì)象,調(diào)試時(shí)尋找錯(cuò)誤可能需要逐級(jí)排查,較為煩瑣。
裝飾者與適配者模式的區(qū)別:
1、適配器模式主要用來(lái)兼容那些不能在一起工作的類,使他們轉(zhuǎn)化為可以兼容目標(biāo)接口,雖然也可以實(shí)現(xiàn)和裝飾者一樣的增加新職責(zé),但目的不在此。
裝飾者模式主要是給被裝飾者增加新職責(zé)的。
2、適配器模式是用新接口來(lái)調(diào)用原接口,原接口對(duì)新系統(tǒng)是不可見(jiàn)或者說(shuō)不可用的。
裝飾者模式原封不動(dòng)的使用原接口,系統(tǒng)對(duì)裝飾的對(duì)象也通過(guò)原接口來(lái)完成使用。
3、適配器是知道被適配者的詳細(xì)情況的(就是那個(gè)類或那個(gè)接口)。
裝飾者只知道其接口是什么,至于其具體類型(是基類還是其他派生類)只有在運(yùn)行期間才知道。
裝飾者和繼承的區(qū)別:
繼承:
優(yōu)點(diǎn):代碼結(jié)構(gòu)清晰,而且實(shí)現(xiàn)簡(jiǎn)單
缺點(diǎn):對(duì)于每一個(gè)的需要增強(qiáng)的類都要?jiǎng)?chuàng)建具體的子類來(lái)幫助其增強(qiáng),這樣會(huì)導(dǎo)致繼承體系過(guò)于龐大。
裝飾者:
優(yōu)點(diǎn):內(nèi)部可以通過(guò)多態(tài)技術(shù)對(duì)多個(gè)需要增強(qiáng)的類進(jìn)行增強(qiáng)
缺點(diǎn):需要內(nèi)部通過(guò)多態(tài)技術(shù)維護(hù)需要增強(qiáng)的類的實(shí)例。進(jìn)而使得代碼稍微復(fù)雜。
使用場(chǎng)景:
1、需要擴(kuò)展一個(gè)類的功能,或給一個(gè)類添加附加職責(zé)。
2、需要?jiǎng)討B(tài)的給一個(gè)對(duì)象添加功能,這些功能可能不明確或者暫時(shí)的,可以隨時(shí)很方便的動(dòng)態(tài)撤銷掉。
3、需要增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能,從而使繼承關(guān)系變的不現(xiàn)實(shí)。
4.、當(dāng)不能采用生成子類的方法進(jìn)行擴(kuò)充時(shí)。一種情況是,可能有大量獨(dú)立的擴(kuò)展,為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸性增長(zhǎng)。另一種情況可能是因?yàn)轭惗x被隱藏,或類定義不能用于生成子類。
轉(zhuǎn)自:java知音
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
IDEA插件之彩虹括號(hào)Rainbow?Brackets使用介紹
這篇文章主要為大家介紹了IDEA插件之彩虹括號(hào)Rainbow?Brackets使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
webuploader 實(shí)現(xiàn)圖片批量上傳功能附實(shí)例代碼
這篇文章主要介紹了webuploader 實(shí)現(xiàn)圖片批量上傳功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-11-11
IntelliJ IDEA 刷題利器 LeetCode 插件詳解
這篇文章主要介紹了IntelliJ IDEA 刷題利器 LeetCode 插件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
Spring data jpa @Query update的坑及解決
這篇文章主要介紹了Spring data jpa @Query update的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
手把手教你實(shí)現(xiàn)idea中配置國(guó)內(nèi)源
idea的國(guó)內(nèi)源配置十分重要,能夠提升程序開(kāi)發(fā)的效率而且也是減少bug的一種有效防范,本文就來(lái)介紹一下idea中配置國(guó)內(nèi)源,具有一定的參考價(jià)值,感興趣的可以了解一下2023-07-07

