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