Java結(jié)構(gòu)性設(shè)計(jì)模式中的裝飾器模式介紹使用
裝飾器模式
概述
裝飾器模式(Decorator Pattern)也稱為包裝模式(Wrapper Pattern),屬于結(jié)構(gòu)型模式。
它是指在不改變?cè)袑?duì)象的基礎(chǔ)之上,允許向一個(gè)現(xiàn)有的對(duì)象添加新的功能,同時(shí)又不改變其結(jié)構(gòu),作為現(xiàn)有的類的一個(gè)包裝。
這種模式創(chuàng)建一個(gè)裝飾類,用來(lái)包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。
提供了比繼承更有單性的替代方案,進(jìn)行擴(kuò)展原有對(duì)象的功能。
裝飾器模式的核心是功能擴(kuò)展。使用裝飾器模式可以透明且動(dòng)態(tài)地?cái)U(kuò)展類的功能。
裝飾器模式主要用于誘明且動(dòng)態(tài)地?cái)U(kuò)展類的功能。
實(shí)現(xiàn)原理
讓裝飾器實(shí)現(xiàn)被包裝類相同的接口,使得裝飾器與被擴(kuò)展類類型一致,并在構(gòu)造函數(shù)中傳入該接口對(duì)象,然后就可以在接口需要實(shí)現(xiàn)的方法中在被包裝類對(duì)象的現(xiàn)有功能上添加新功能。
由于裝飾器與被包裝類屬于同一類型,且構(gòu)造函數(shù)的參數(shù)為其實(shí)現(xiàn)接口類,因此裝飾器模式具備嵌套擴(kuò)展功能,因此就能使用裝飾器模式一層層的對(duì)最底層被包裝類進(jìn)行功能擴(kuò)展。
在JDK中,IO相關(guān)包下大量使用裝飾器模式,如BufferedReader、InputStream、OutputStream等類
主要角色
裝飾器模式主要包含4種角色
1.抽象組件(Component)
抽象組件可以是一個(gè)接口或者抽象類,其充當(dāng)被裝飾類的原始對(duì)象,規(guī)定了被裝飾對(duì)象的行為。
2.具體組件(ConcreteComponent)
具體組件實(shí)現(xiàn)/繼承抽象組件的一個(gè)具體對(duì)象,即被裝飾對(duì)象。
3.抽象裝飾器(Decorator)
通用的裝飾具體組件的裝飾器,其內(nèi)部必然有一個(gè)屬性指向抽象組件;其實(shí)現(xiàn)一般是一個(gè)抽象類,主要是為了讓其子類按照其構(gòu)造形式傳入一個(gè)抽象組件,這是強(qiáng)制的通用行為。
如果系統(tǒng)中裝飾邏輯單一,并不需要實(shí)現(xiàn)許多裝飾器,那么可以直接省略該類,而直接實(shí)現(xiàn)一個(gè)具體裝飾器即可。
4.具體裝飾器(ConcreteDecorator)
抽象裝飾器的具體實(shí)現(xiàn)類,理論上,每個(gè)具體組件都擴(kuò)展了抽象組件對(duì)象的一種功能。
應(yīng)用場(chǎng)景
1.用于擴(kuò)展一個(gè)類的功能或給一個(gè)類添加附加職責(zé)。
2.動(dòng)態(tài)的給一個(gè)對(duì)象添加功能,這些功能可以再動(dòng)態(tài)的澈銷。
3.需要為一批的兄弟類進(jìn)行改裝或加裝功能。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1.裝飾器是繼承的補(bǔ)充,比繼承靈活,不改變?cè)袑?duì)象的情況下動(dòng)態(tài)地給一個(gè)對(duì)象擴(kuò)展功能,即插即用。
2.裝飾器完全遵守開閉原則。
缺點(diǎn):
1.會(huì)出現(xiàn)更多的代碼,更多的類,增加程序復(fù)雜性。
2.通過(guò)使用不同裝飾類以及這些裝飾類的排列組合,可以實(shí)現(xiàn)不同效果。
3.動(dòng)態(tài)裝飾時(shí),多層裝飾時(shí)會(huì)更復(fù)雜。
裝飾器模式的基本使用
創(chuàng)建抽象組件
創(chuàng)建Phone抽象類
public abstract class Phone { public abstract String call(); public abstract double price(); }
具體組件
創(chuàng)建最基本具有打電話功能的手機(jī)
public class BasePhone extends Phone { @Override public String call() { return "BasePhone call"; } @Override public double price() { return 0.1; } }
抽象裝飾器
創(chuàng)建一個(gè)抽象裝飾器來(lái)擴(kuò)展該只具備基本功能的手機(jī)
public abstract class PhoneDecorator extends Phone { private Phone phone; public PhoneDecorator(Phone phone) { this.phone = phone; } @Override public String call() { return phone.call(); } @Override public double price() { return phone.price(); } /** * 擴(kuò)展功能 */ public abstract void sendMsg(); }
具體裝飾器
public class SatellitePhoneDecorator extends PhoneDecorator{ public SatellitePhoneDecorator(Phone phone) { super(phone); } public void sendMsg() { System.out.println("PhoneCallDecorator sendMsg"); } @Override public String call() { return "SatellitePhone call"; } @Override public double price() { return super.price()+100; } }
客戶端調(diào)用
public static void main(String[] args) { // 創(chuàng)建需要被裝飾的原始對(duì)象(即要被裝飾的對(duì)象) Phone phone = new BasePhone(); System.out.println("使用: "+phone.call()+" 方式打電話,每分鐘單價(jià):" + phone.price()); // 給對(duì)象透明的增加額外功能并調(diào)用 PhoneDecorator phoneDecorator = new SatellitePhoneDecorator(phone); System.out.println("使用: "+phoneDecorator.call()+" 方式打電話,每分鐘單價(jià):" + phoneDecorator.price()); // 裝飾器也可以裝飾具體的裝飾對(duì)象,相當(dāng)于給對(duì)象在增加的功能基礎(chǔ)上在添加功能,這里體現(xiàn)在單價(jià)100.1基礎(chǔ)上再+100 PhoneDecorator satellitePhoneDecorator = new SatellitePhoneDecorator(phoneDecorator); System.out.println("使用: "+satellitePhoneDecorator.call()+" 方式打電話,每分鐘單價(jià):" + satellitePhoneDecorator.price()); satellitePhoneDecorator.sendMsg(); }
使用: BasePhone call 方式打電話,每分鐘單價(jià):0.1
使用: SatellitePhone call 方式打電話,每分鐘單價(jià):100.1
使用: SatellitePhone call 方式打電話,每分鐘單價(jià):200.1
PhoneCallDecorator sendMsg
到此這篇關(guān)于Java結(jié)構(gòu)性設(shè)計(jì)模式中的裝飾器模式介紹使用的文章就介紹到這了,更多相關(guān)Java裝飾器模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Boot?使用?SSE?方式向前端推送數(shù)據(jù)詳解
這篇文章主要介紹了Spring?Boot?使用SSE方式向前端推送數(shù)據(jù)詳解,SSE簡(jiǎn)單的來(lái)說(shuō)就是服務(wù)器主動(dòng)向前端推送數(shù)據(jù)的一種技術(shù),它是單向的,也就是說(shuō)前端是不能向服務(wù)器發(fā)送數(shù)據(jù)的2022-08-08淺談java+內(nèi)存分配及變量存儲(chǔ)位置的區(qū)別
下面小編就為大家?guī)?lái)一篇淺談java+內(nèi)存分配及變量存儲(chǔ)位置的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-08-08Springboot詳解實(shí)現(xiàn)食品倉(cāng)庫(kù)管理系統(tǒng)流程
這是一個(gè)使用Springboot開發(fā)的食品倉(cāng)庫(kù)管理系統(tǒng),是為商家提供商品貨物進(jìn)銷存的信息化管理系統(tǒng),具有一個(gè)倉(cāng)庫(kù)管理系統(tǒng)該有的所有功能,感興趣的朋友快來(lái)看看吧2022-06-06Zookeeper如何實(shí)現(xiàn)分布式服務(wù)配置中心詳解
Zookeeper在實(shí)際使用場(chǎng)景很多,比如配置中心,分布式鎖,注冊(cè)中心等,下面這篇文章主要給大家介紹了關(guān)于Zookeeper如何實(shí)現(xiàn)分布式服務(wù)配置中心的相關(guān)資料,需要的朋友可以參考下2021-11-11IDEA2020 Plugins不能用的解決辦法及Plugins 搜索不了插件的問(wèn)題
這篇文章主要介紹了IDEA2020 Plugins不能用的解決辦法,文中給大家介紹了Intellij IDEA 2020.1 的Plugins 搜索不了插件,連接超時(shí)的問(wèn)題,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2020-06-06Java線性結(jié)構(gòu)中的雙向鏈表實(shí)現(xiàn)原理
這篇文章將給大家詳細(xì)講解雙向鏈表的內(nèi)容,尤其是會(huì)通過(guò)代碼來(lái)進(jìn)行鏈表的操作,文中的代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2023-07-07java實(shí)現(xiàn)圖片上傳至本地實(shí)例詳解
我們給大家分享了關(guān)于java實(shí)現(xiàn)圖片上傳至本地的實(shí)例以及相關(guān)代碼,有需要的朋友參考下。2018-08-08SpringBoot參數(shù)校驗(yàn)的方法總結(jié)
今天帶大家學(xué)習(xí)SpringBoot參數(shù)校驗(yàn)的方法,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05