漫畫(huà)設(shè)計(jì)模式:什么是 “裝飾器模式” ?
————— 第二天 —————
————————————
裝飾器模式都包含哪些核心角色呢?
1. Component接口
在我們上面的例子中,Component接口相當(dāng)于汽車(chē)接口,所有的被包裝類(lèi)、包裝類(lèi),都繼承于這個(gè)接口。
2. ConcreteComponent類(lèi)
ConcreteComponent類(lèi)是被包裝的實(shí)現(xiàn)類(lèi)。在例子中,奔馳汽車(chē)、寶馬汽車(chē)、特斯拉汽車(chē)都屬于這個(gè)角色。
3. Decorator抽象類(lèi)
所有的包裝類(lèi),都繼承自Decorator抽象類(lèi),而Decorator類(lèi)又實(shí)現(xiàn)了Component接口,這么做是為了實(shí)現(xiàn)多層嵌套包裝。
4. ConcreteDecorator類(lèi)
具體的包裝類(lèi),用于擴(kuò)充被包裝類(lèi)的功能,比如例子中的自動(dòng)駕駛功能、飛行功能擴(kuò)展。
這四大核心角色的關(guān)系是怎樣的呢?我們可以用裝飾器模式的UML類(lèi)圖來(lái)表達(dá):
首先是汽車(chē)接口,也就是Component這個(gè)角色,里面定義了run這個(gè)行為:
public interface Car { void run(); }
接下來(lái)是各種汽車(chē)的實(shí)現(xiàn)類(lèi),也就是ConcreteComponent角色,不同的汽車(chē)對(duì)于run行為有著不同的實(shí)現(xiàn):
public class BenzCar implements Car{ @Override public void run() { System.out.println("奔馳開(kāi)車(chē)了!"); } } public class BmwCar implements Car{ @Override public void run() { System.out.println("寶馬開(kāi)車(chē)了!"); } } public class TeslaCar implements Car{ @Override public void run() { System.out.println("特斯拉開(kāi)車(chē)了!"); } }
下面是裝飾器的抽象類(lèi),也就是Decorator角色,這個(gè)角色包含了被裝飾的成員對(duì)象:
public class CarDecorator implements Car { protected Car decoratedCar; public CarDecorator(Car decoratedCar){ this.decoratedCar = decoratedCar; } public void run(){ decoratedCar.run(); } }
或許有人會(huì)覺(jué)得奇怪,為什么裝飾器類(lèi)也要實(shí)現(xiàn)Car接口呢?這正是裝飾器模式的靈活之處。
繼承自Car接口,可以讓每一個(gè)裝飾器本身也可以被更外層的裝飾器所包裝,包裝的方式就是把Car對(duì)象作為參數(shù),傳入到外層裝飾器的構(gòu)造函數(shù)當(dāng)中。
接下來(lái)是具體的裝飾器實(shí)現(xiàn)類(lèi),也就是ConcreteDecorator角色。這些裝飾器同樣實(shí)現(xiàn)了run的行為,一方面會(huì)調(diào)用被包裝對(duì)象的run方法,一方面會(huì)進(jìn)行某些擴(kuò)展操作(比如自動(dòng)駕駛、飛行):
public class AutoCarDecorator extends CarDecorator { public AutoCarDecorator(Car decoratedCar){ super(decoratedCar); } @Override public void run(){ decoratedCar.run(); autoRun(); } private void autoRun(){ System.out.println("開(kāi)啟自動(dòng)駕駛"); }} public class FlyCarDecorator extends CarDecorator { public FlyCarDecorator(Car decoratedCar){ super(decoratedCar); } @Override public void run(){ decoratedCar.run(); fly(); } private void fly(){ System.out.println("開(kāi)啟飛行汽車(chē)模式"); } }
最后,是我們的客戶端類(lèi)??蛻舳祟?lèi)負(fù)責(zé)創(chuàng)建被包裝對(duì)象和裝飾者,并決定如何進(jìn)行包裝和執(zhí)行:
public class Client { public static void main(String[] args) { Car benzCar = new BenzCar(); Car bmwCar = new BmwCar(); Car teslaCar = new TeslaCar(); //創(chuàng)建自動(dòng)駕駛的奔馳汽車(chē) CarDecorator autoBenzCar = new AutoCarDecorator(benzCar); //創(chuàng)建飛行的、自動(dòng)駕駛的寶馬汽車(chē) CarDecorator flyAutoBmwCar = new FlyCarDecorator(new AutoCarDecorator(bmwCar)); benzCar.run(); bmwCar.run(); teslaCar.run(); autoBenzCar.run(); flyAutoBmwCar.run(); } }
以輸入流為例,為了滿足不同輸入場(chǎng)景,JDK設(shè)計(jì)了多種多樣的輸入流,包括ByteArrayInputStream、FileInputStream等等。
這些輸入流都繼承自共同的抽象類(lèi):InputStream。
與此同時(shí),為了給這些輸入流帶來(lái)功能上的擴(kuò)展,JDK設(shè)計(jì)了一個(gè)裝飾器類(lèi),FilterInputStream。該類(lèi)繼承自InputStream,并且“組合”了InputStream成員對(duì)象。
從FilterInputStream類(lèi)派生出了許多裝飾器子類(lèi),包括BufferedInputStream,DataInputStream等等,分別提供了輸入流緩沖,以及從輸入流讀取Java基本數(shù)據(jù)類(lèi)型等額外功能。
—————END—————
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!