Java设计模式-装饰器模式 理论代码相结合
繼Java設計模式適配器模式后的裝飾器模式來啦,讓我們一起看看吧。
會了就當復習丫,不會來一起來看看吧。
很喜歡一句話:“八小時內謀生活,八小時外謀發展”。
如果你也喜歡,讓我們一起堅持吧!!
共勉😁
一張舊圖,恍惚間念起舊人
Java設計模式-裝飾器模式
- 一、裝飾器模式介紹
- 1)引入:
- 2)概述
- 3)角色結構
- 4)使用場景
- 5)舉個例子
- 二、裝飾器模式實現
- 2.1、前言
- 2.2、代碼實現
- 三、總結
- 1、使用場景
- 2、優點:
- 3、缺點:
- 四、自言自語
一、裝飾器模式介紹
1)引入:
上班族大多都有睡懶覺的習慣,每天早上上班時間都很緊張,于是很多人為了多睡一會,就會用方便的方式解決早餐問題。有些人早餐可能會吃煎餅,煎餅中可以加雞蛋,也可以加香腸,但是不管怎么“加碼”,都還是一個煎餅。在現實生活中,常常需要對現有產品增加新的功能或美化其外觀,如房子裝修、相片加相框等,都是裝飾器模式。在我們自己行業就是這個東西得加需求啦
在軟件開發過程中,有時想用一些現存的組件。這些組件可能只是完成了一些核心功能。但在不改變其結構的情況下,可以動態地擴展其功能。所有這些都可以釆用裝飾器模式來實現。
2)概述
裝飾器(Decorator)模式的定義:指在不改變現有對象結構的情況下,動態地給該對象增加一些職責(即增加其額外功能)的模式,它屬于對象結構型模式。
3)角色結構
4)使用場景
1、擴展一個類的功能。
2、動態增加功能,動態撤銷。
就是主要為了方便擴展。
5)舉個例子
快餐店有炒面、炒飯這些快餐,可以額外附加雞蛋、火腿、培根這些配菜,當然加配菜需要額外加錢,每個配菜的價錢通常不太一樣,那么計算總價就會顯得比較麻煩。
這是一個快餐店的例子,這么咋一看,感覺還可以,但是如果不再局限于炒飯FriedRice和炒面FriedNoodies中,想要做一些擴展,例如加一個炒粉Fried sweet potato powder,就又要額外增加一個整體,再往下重復實現雞蛋、培根等等的類。增加這么多,就會造成類爆炸,特別多,就非常不合適。
會產生過多的子類。欲知后事如何,請看下文👇。
二、裝飾器模式實現
2.1、前言
接下來,我們用裝飾器的模式來重構一下代碼,看看會產生哪些方面的變化哈。也來一起看看裝飾器模式的精髓。
不過圖也要改變一下啦,變成這樣子的啦:
我們先來講講這張圖和上一張圖的區別。
這么看好像還是少了點東西,結合代碼我們一起來看一看。
我們把角色定位一下:
2.2、代碼實現
👇下面看代碼一步一步實現看一下:
FastFoot快餐接口:即抽象構件
//快餐接口 public abstract class FastFood {private float price;private String desc;public FastFood() { }public FastFood(float price, String desc) {this.price = price;this.desc = desc;}//set、get 方法public void setPrice(float price) { this.price = price; }public float getPrice() { return price; }public String getDesc() { return desc; }public void setDesc(String desc) { this.desc = desc; }public abstract float cost(); //獲取價格 }FriedRice和FriedNoodies 即炒飯炒面 即具體構件
//炒飯 public class FriedRice extends FastFood {public FriedRice() {super(10, "炒飯");}// 獲取價格public float cost() {return getPrice();} }//炒面 public class FriedNoodles extends FastFood {public FriedNoodles() {super(12, "炒面");}// 獲取價格public float cost() {return getPrice();} }Garnish 即配料類 抽象裝飾
public abstract class Garnish extends FastFood {private FastFood fastFood;public FastFood getFastFood() { return fastFood; }public void setFastFood(FastFood fastFood) { this.fastFood = fastFood; }public Garnish(FastFood fastFood, float price, String desc) {super(price,desc);this.fastFood = fastFood;} }Egg和Bacon類,即雞蛋和培根為 具體裝飾類
//雞蛋配料 public class Egg extends Garnish {public Egg(FastFood fastFood) { super(fastFood,1,"雞蛋"); }// 這里是返回了 炒飯加 雞蛋的錢的public float cost() { return getPrice() + getFastFood().getPrice(); }@Overridepublic String getDesc() { return super.getDesc() + getFastFood().getDesc(); } }//培根配料 public class Bacon extends Garnish {public Bacon(FastFood fastFood) { super(fastFood,2,"培根"); }@Overridepublic float cost() { return getPrice() + getFastFood().getPrice(); }@Overridepublic String getDesc() { return super.getDesc() + getFastFood().getDesc(); } }測試類:
public class Client {public static void main(String[] args) {//點一份炒飯FastFood food = new FriedRice();//花費的價格System.out.println(food.getDesc() + " " + food.cost() + "元");System.out.println("========");//點一份加雞蛋的炒飯FastFood food1 = new FriedRice();food1 = new Egg(food1);//花費的價格System.out.println(food1.getDesc() + " " + food1.cost() + "元");System.out.println("========");//點一份加培根的炒面FastFood food2 = new FriedNoodles();food2 = new Bacon(food2);//花費的價格System.out.println(food2.getDesc() + " " + food2.cost() + "元");} }這就解決了我們剛開始的一個問題,如果還需要進行擴張,需要增加一個炒河粉 那么只需要寫一個炒河粉的類來繼承FastFoot快餐類即可,如需增加配料,也只要寫個配料類來繼承Garnish配料類即可。其他代碼均不用改變,完全符合開閉原則。也比原本減少了類的產生。😁
三、總結
1、使用場景
-
當不能采用繼承的方式對系統進行擴充或者采用繼承不利于系統擴展和維護時。
不能采用繼承的情況主要有兩類:
- 第一類是系統中存在大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長;
- 第二類是因為類定義不能繼承(如final類)
在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
-
當對象的功能要求可以動態地添加,也可以再動態地撤銷時。
2、優點:
3、缺點:
- 裝飾器模式會增加許多子類,過度使用會增加程序得復雜性。多層裝飾比較復雜。
四、自言自語
你卷我卷,大家卷,什么時候這條路才是個頭啊。😇(還是直接上天吧)
有時候也想停下來歇一歇,一直做一個事情,感覺挺難堅持的。😁
你好,如果你正巧看到這篇文章,并且覺得對你有益的話,就給個贊吧,讓我感受一下分享的喜悅吧,蟹蟹。🤗
如若有寫的有誤的地方,也請大家不嗇賜教!!
同樣如若有存在疑惑的地方,請留言或私信,定會在第一時間回復你。
持續更新中
總結
以上是生活随笔為你收集整理的Java设计模式-装饰器模式 理论代码相结合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java设计模式-代理模式 理论代码相结
- 下一篇: Java设计模式-桥接模式 理论代码相结