加糖加冰加牛奶——装饰模式
裝飾模式
? Decorator Pattern:屬于GoF23種設(shè)計(jì)模式中結(jié)構(gòu)型設(shè)計(jì)模式的一種,又被稱為裝飾者模式。
? 簡單的說,裝飾模式/裝飾者模式就是給一個現(xiàn)有的類,在不改變這個類的情況下,動態(tài)的給這個類進(jìn)行擴(kuò)展,添加新的東西,比如說添加新的功能。
? 動態(tài)的意思也就是說不需要這個類創(chuàng)建的時候指定,完全可以等這個類創(chuàng)建完成了之后,已經(jīng)完全成為了一個“活蹦亂跳”的對象了之后,再給他添加新的東西,不需要寫死,而是想要什么時候加就什么時候加,想要加什么就加什么。
結(jié)構(gòu)
-
給出一張簡易的裝飾者模式的結(jié)構(gòu)圖片吧,分析一下下
-
有一個抽象對象,這個是干什么的呢?這個是被裝飾者對象,簡單的說就是我們需要在這個對象上進(jìn)行裝飾,這樣就好理解了吧。
至于為什么要對被裝飾者進(jìn)行抽象,因?yàn)橐嫦蚪涌诰幊痰穆?#xff0c;也可以留出更大的擴(kuò)展空間不是。
-
緊接著的就是具體的對象了,也就是真實(shí)的被裝飾者。
-
裝飾者模式主要的還是裝飾,那么顯然對于裝飾的抽象是不可避免的,也不會就有一個功能需要裝飾的吧,如果真的有那也要進(jìn)行抽象以下,畢竟,也需,過不了多久你的PM和你說需求要改了呢?
這個里面需要注意的就是維護(hù)了一個被裝飾者對象,因?yàn)樵趯?shí)際的代碼中我們應(yīng)該對這個被裝飾者進(jìn)行包裝,但是前提是我們不能修改這個被裝飾者,也就是需要動態(tài)兩個字的體現(xiàn),具體的應(yīng)用可以看后面的代碼部分可能會好理解一點(diǎn)。
-
下面的就是所有的具體如何去裝飾的實(shí)現(xiàn)類了。
舉例說明
對于裝飾著模式來說,最容易體會到的,那就是學(xué)習(xí)JAVA的IO流的時候了,那里面的一層層的包裝,真的是眼花繚亂。
比如想要生成一個字符緩沖流,應(yīng)該如何???
BufferedReader stringBuffer = new BufferedReader(new InputStreamReader(new FileInputStream("demo.txt")));哈哈,這就是層層裝飾啊,從一個文本輸入流,變成字符串輸入流,變成帶緩沖的字符緩沖流。
OK,我們也可以面向生活一點(diǎn)兒,有沒有小伙伴知道“加碼子”是啥意思啊?早餐的時候,首先呢點(diǎn)了一碗素面,發(fā)現(xiàn)不行,太過于單調(diào),有點(diǎn)了一個豆干,還是不行,緊接著一個雞蛋,還是不行,有加了一份牛肉…越來越多,越來越多,原先的一碗素面已經(jīng)是“五彩繽紛”了啊。
再來個小栗子,也是闊以的啊,比如去喝個奶茶,有原味奶茶的吧,但是沒意思啊,味道不好,但是呢,我們可以加?xùn)|西進(jìn)去啊,珍珠或者椰果?加冰或者不加冰?都是可以的嘛
用筆者自己喜歡的方式的話,那就是游戲里面人物的時裝了,想當(dāng)初,毒奶粉的時候,筆者為了黃金天空套,又不想充錢,那是天天搬磚,天天搬磚換代幣卷,一件一件湊齊的啊,看著自己的角色一件件穿上時裝,嘿嘿裝飾模式之下變得金閃閃啊(不是那個金閃閃啊,這里可沒有咖喱棒)。
注意
其實(shí)呢這個裝飾模式的結(jié)構(gòu)是可以簡化的,上面給出的是一個完整的結(jié)構(gòu)。可以簡化的部分很顯然嘛,就是兩個抽象類可以去掉撒。
也就是說,只有一個被裝飾者對象的時候,被裝飾者的抽象類咱就不要了,抽象裝飾直接繼承這個對象就成了啊。
還有一種呢就是只有一個具體的裝飾實(shí)現(xiàn)類,那就直接不要抽象裝飾類就行了唄,子類是可以頂替父類的嘛。
裝飾著的優(yōu)點(diǎn)的話,應(yīng)該就是可以創(chuàng)建五花八門的各種各樣的實(shí)際對象吧。這樣子顯得擴(kuò)展更加的靈活,而且自由性很高很高的。
但是捏,東西雖好,也是不可以亂用的,可以看到這個位置有兩個大分支線也就是兩個抽象類的部分了,如果東西一多,那產(chǎn)生的小小的子類,估計(jì)可以看的你頭疼…
一個小DEMO
場景
一個簡單的場景設(shè)計(jì)吧,記得那是一天下午,壓馬路的筆者看到了路邊的奶茶店,正好口渴準(zhǔn)備去點(diǎn)一杯,可是面前的價目表看的真的是眼花繚亂啊,只好準(zhǔn)備自己搭配一個,嘿嘿,來一杯原味奶茶,加上椰果,加上冰,珍珠嘛,還是不需要了吧。
用代碼模擬一下這個場景的實(shí)現(xiàn)吧!
抽象類還是接口,那就看大家的習(xí)慣吧。
首先定義被裝飾者對象——奶茶的話,估摸著算是飲料???
package com.decorator; /*** 裝飾者模式——抽象對象——也就是被裝飾者對象的抽象對象* DEMO中的話就是飲料了* @author WQ*/ public abstract class Drinks {public abstract void show(); }來個奶茶類,這就是具體的被裝飾者對象了!
package com.decorator; /*** 裝飾者模式——具體的被裝飾者對象* DEMO中的話就是奶茶了* @author WQ*/ public class MilkyTea extends Drinks{@Overridepublic void show() {System.out.println("我是一杯奶茶啊!");} }定義個抽象的裝飾類,這里的話抽象起來,算作配料???
package com.decorator; /*** 裝飾者模式——抽象裝飾對象* DEMO中的話就是配料吧* @author WQ*/ public abstract class Batching extends Drinks{/*** 維護(hù)一個被裝飾著對象* (這里是面向接口編程)* 注意權(quán)限修飾符是protected 這個類的子類是可以直接使用的*/protected Drinks drink;/*** 說明一下下* 抽象類是可以有構(gòu)造方法的* 只是不能直接創(chuàng)建抽象類的實(shí)例對象而已* @param drink*/public Batching(Drinks drink) {this.drink = drink;}@Overridepublic void show() {drink.show();} }真實(shí)的配料也需要上場了啊,這部分就是具體的裝飾類了。
package com.decorator; /*** 裝飾者模式——具體裝飾類對象* 這是珍珠哦* @author WQ*/ public class Pearl extends Batching{/*** 自然的需要維護(hù)一個被裝飾者對象的嘛* @param drink*/public Pearl(Drinks drink) {super(drink);}/*** 這里還需要覆蓋掉父類的方法* 父類里面只是對被裝飾著對象調(diào)用了一下,* 我們需要裝飾啊*/@Overridepublic void show() {/*** 這里首先是調(diào)用了父類的方法的* 我們是對原有的對象進(jìn)行包裝,* 那么應(yīng)該保證的是原有對象的功能應(yīng)該是完善的,* 如果這里不調(diào)用的話,那么我們編寫出來的結(jié)果就沒有被裝飾的類了。*/super.show();decorate(drink);}/*** 這個位置就是具體的被裝飾的邏輯了,* 雖然這里只有一個小小的輸出,* 但是實(shí)現(xiàn)更為復(fù)雜的邏輯的時候還是需要抽出來成為一個方法的*/private void decorate(Drinks drink) {System.out.print("加珍珠~");} } //-------------------------------------------------------------------- package com.decorator; /*** 裝飾者模式——具體裝飾類對象* 這是椰果哦* @author WQ*/ public class Coconut extends Batching{public Coconut(Drinks drink) {super(drink);}@Overridepublic void show() {super.show();decorate(drink);}private void decorate(Drinks drink) {System.out.print("加椰果~");} } //---------------------------------------------------------------- package com.decorator; /*** 裝飾者模式——具體裝飾類對象* 這是冰哦* @author WQ*/ public class Ice extends Batching{public Ice(Drinks drink) {super(drink);}@Overridepublic void show() {super.show();decorate(drink);}private void decorate(Drinks drink) {System.out.print("加冰~");} }編個測試類
package com.decorator; /*** 裝飾者模式——測試類部分* @author WQ*/ public class Main {public static void main(String[] args) {//被裝飾者對象Drinks drink = new MilkyTea();//這一次來個全加Batching batching1 = new Pearl(drink);//注意傳進(jìn)去的參數(shù)不是drink了,而是被裝飾了以后的對象了啊//對象已經(jīng)被打包了,原來的對象穿了一套“衣服”了Batching batching2 = new Coconut(batching1);//這也是為啥裝飾類也要繼承被裝飾類的原因哦Batching batching3 = new Ice(batching2);batching3.show();System.out.println();//換個我們熟悉的方式的Batching batching = new Ice(new Pearl(new MilkyTea()));batching.show();} }測試結(jié)果
我是一杯奶茶啊! 加珍珠~加椰果~加冰~ 我是一杯奶茶啊! 加珍珠~加冰~完成!
總結(jié)
以上是生活随笔為你收集整理的加糖加冰加牛奶——装饰模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个人的时候,学会坦然。
- 下一篇: kafka数据同步Elasticsear