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