漫畫設(shè)計(jì)模式:什么是 “裝飾器模式” ?


—————? 第二天? —————








————————————


























裝飾器模式都包含哪些核心角色呢?
1. Component接口
在我們上面的例子中,Component接口相當(dāng)于汽車接口,所有的被包裝類、包裝類,都繼承于這個(gè)接口。
2. ConcreteComponent類
ConcreteComponent類是被包裝的實(shí)現(xiàn)類。在例子中,奔馳汽車、寶馬汽車、特斯拉汽車都屬于這個(gè)角色。
3.?Decorator抽象類
所有的包裝類,都繼承自Decorator抽象類,而Decorator類又實(shí)現(xiàn)了Component接口,這么做是為了實(shí)現(xiàn)多層嵌套包裝。
4.?ConcreteDecorator類
具體的包裝類,用于擴(kuò)充被包裝類的功能,比如例子中的自動(dòng)駕駛功能、飛行功能擴(kuò)展。
這四大核心角色的關(guān)系是怎樣的呢?我們可以用裝飾器模式的UML類圖來(lái)表達(dá):


首先是汽車接口,也就是Component這個(gè)角色,里面定義了run這個(gè)行為:
public?interface?Car?{
????void?run();
}
接下來(lái)是各種汽車的實(shí)現(xiàn)類,也就是ConcreteComponent角色,不同的汽車對(duì)于run行為有著不同的實(shí)現(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角色,這個(gè)角色包含了被裝飾的成員對(duì)象:
public?class?CarDecorator?implements?Car?{
????protected?Car?decoratedCar;
????public?CarDecorator(Car?decoratedCar){
????????this.decoratedCar?=?decoratedCar;
????}
????public?void?run(){
????????decoratedCar.run();
????}
}
或許有人會(huì)覺得奇怪,為什么裝飾器類也要實(shí)現(xiàn)Car接口呢?這正是裝飾器模式的靈活之處。
繼承自Car接口,可以讓每一個(gè)裝飾器本身也可以被更外層的裝飾器所包裝,包裝的方式就是把Car對(duì)象作為參數(shù),傳入到外層裝飾器的構(gòu)造函數(shù)當(dāng)中。
接下來(lái)是具體的裝飾器實(shí)現(xiàn)類,也就是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("開啟自動(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("開啟飛行汽車模式");
????}
}
最后,是我們的客戶端類。客戶端類負(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)駕駛的奔馳汽車
????????CarDecorator?autoBenzCar?=?new?AutoCarDecorator(benzCar);
????????//創(chuàng)建飛行的、自動(dòng)駕駛的寶馬汽車
????????CarDecorator?flyAutoBmwCar?=?new?FlyCarDecorator(new?AutoCarDecorator(bmwCar));
????????benzCar.run();
????????bmwCar.run();
????????teslaCar.run();
????????autoBenzCar.run();
????????flyAutoBmwCar.run();
????}
}



以輸入流為例,為了滿足不同輸入場(chǎng)景,JDK設(shè)計(jì)了多種多樣的輸入流,包括ByteArrayInputStream、FileInputStream等等。
這些輸入流都繼承自共同的抽象類:InputStream。
與此同時(shí),為了給這些輸入流帶來(lái)功能上的擴(kuò)展,JDK設(shè)計(jì)了一個(gè)裝飾器類,FilterInputStream。該類繼承自InputStream,并且“組合”了InputStream成員對(duì)象。
從FilterInputStream類派生出了許多裝飾器子類,包括BufferedInputStream,DataInputStream等等,分別提供了輸入流緩沖,以及從輸入流讀取Java基本數(shù)據(jù)類型等額外功能。


—————END—————
歡迎關(guān)注微信公眾號(hào):互聯(lián)網(wǎng)全棧架構(gòu),收取更多有價(jià)值的信息。
