Java設計模式實戰:裝飾模式在星巴克咖啡系統中的應用

一、裝飾模式簡介

? ? ? ?裝飾模式(Decorator Pattern)是一種結構型設計模式,它允許向一個現有的對象添加新的功能,同時又不改變其結構。這種模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。

二、星巴克咖啡系統設計

根據提供的UML類圖,我們來設計一個星巴克咖啡下單系統,該系統可以計算不同咖啡和調料組合的價格。

系統組成

  1. 抽象組件(Beverage):相當于Component類,是所有咖啡和調料的基類

  2. 具體組件:HouseBlend、Expresso、DarkRoast、Decaf,代表不同類型的咖啡

  3. 裝飾器(CondimentDecorator):抽象裝飾類

  4. 具體裝飾器:Milk、Mocha、Soy、Whip,代表不同的調料

三、代碼實現

1. 抽象組件(Beverage)

/*** 抽象組件 - 飲料基類* 相當于裝飾模式中的Component角色*/
public abstract class Beverage {// 飲料描述,初始為"Unknown Beverage"String description = "Unknown Beverage";/*** 獲取飲料描述* @return 飲料描述字符串*/public String getDescription() {return description;}/*** 計算飲料價格 - 抽象方法,由子類實現* @return 飲料價格*/public abstract double cost();
}

2. 具體組件(各種咖啡類型)

2.1 HouseBlend 咖啡

/*** 具體組件 - 混合咖啡*/
public class HouseBlend extends Beverage {public HouseBlend() {description = "House Blend Coffee";}@Overridepublic double cost() {return 0.89;  // 基礎價格0.89美元}
}

2.2 Expresso 咖啡

/*** 具體組件 - 濃縮咖啡*/
public class Expresso extends Beverage {public Expresso() {description = "Expresso";}@Overridepublic double cost() {return 1.99;  // 基礎價格1.99美元}
}

2.3 DarkRoast 咖啡

/*** 具體組件 - 深焙咖啡*/
public class DarkRoast extends Beverage {public DarkRoast() {description = "Dark Roast Coffee";}@Overridepublic double cost() {return 0.99;  // 基礎價格0.99美元}
}

2.4 Decaf 咖啡

/*** 具體組件 - 低因咖啡*/
public class Decaf extends Beverage {public Decaf() {description = "Decaf Coffee";}@Overridepublic double cost() {return 1.05;  // 基礎價格1.05美元}
}

3. 抽象裝飾器(CondimentDecorator)

/*** 抽象裝飾器 - 調料裝飾器基類* 繼承自Beverage,所以裝飾器可以嵌套裝飾器*/
public abstract class CondimentDecorator extends Beverage {/*** 獲取完整描述 - 抽象方法* 每個具體裝飾器需要實現如何添加自己的描述*/@Overridepublic abstract String getDescription();
}

4. 具體裝飾器(各種調料)

4.1 Milk 牛奶

/*** 具體裝飾器 - 牛奶*/
public class Milk extends CondimentDecorator {// 被裝飾的飲料Beverage beverage;public Milk(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ", Milk";  // 添加牛奶描述}@Overridepublic double cost() {return beverage.cost() + 0.10;  // 增加0.10美元}
}

4.2 Mocha 摩卡

/*** 具體裝飾器 - 摩卡*/
public class Mocha extends CondimentDecorator {Beverage beverage;public Mocha(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ", Mocha";  // 添加摩卡描述}@Overridepublic double cost() {return beverage.cost() + 0.20;  // 增加0.20美元}
}

4.3 Soy 豆漿

/*** 具體裝飾器 - 豆漿*/
public class Soy extends CondimentDecorator {Beverage beverage;public Soy(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ", Soy";  // 添加豆漿描述}@Overridepublic double cost() {return beverage.cost() + 0.15;  // 增加0.15美元}
}

4.4 Whip 奶泡

/*** 具體裝飾器 - 奶泡*/
public class Whip extends CondimentDecorator {Beverage beverage;public Whip(Beverage beverage) {this.beverage = beverage;}@Overridepublic String getDescription() {return beverage.getDescription() + ", Whip";  // 添加奶泡描述}@Overridepublic double cost() {return beverage.cost() + 0.10;  // 增加0.10美元}
}

5. 客戶端使用示例

/*** 星巴克咖啡店 - 客戶端代碼*/
public class StarbuzzCoffee {public static void main(String args[]) {// 示例1:一杯純EspressoBeverage beverage1 = new Expresso();System.out.println(beverage1.getDescription() + " $" + beverage1.cost());// 示例2:DarkRoast加雙份Mocha和WhipBeverage beverage2 = new DarkRoast();beverage2 = new Mocha(beverage2);  // 第一次裝飾:加Mochabeverage2 = new Mocha(beverage2);  // 第二次裝飾:再加Mochabeverage2 = new Whip(beverage2);   // 第三次裝飾:加WhipSystem.out.println(beverage2.getDescription() + " $" + beverage2.cost());// 示例3:HouseBlend加Soy、Mocha和WhipBeverage beverage3 = new HouseBlend();beverage3 = new Soy(beverage3);   // 第一次裝飾:加Soybeverage3 = new Mocha(beverage3);  // 第二次裝飾:加Mochabeverage3 = new Whip(beverage3);   // 第三次裝飾:加WhipSystem.out.println(beverage3.getDescription() + " $" + beverage3.cost());}
}

四、代碼結構說明

  1. Beverage?是所有飲料的基類,定義了基本接口

  2. 具體咖啡類型(HouseBlend、Expresso等)繼承Beverage,實現具體價格

  3. CondimentDecorator是裝飾器基類,也繼承自Beverage

  4. 具體調料(Milk、Mocha等)繼承CondimentDecorator,包裝一個Beverage對象

  5. 客戶端可以自由組合咖啡和調料,通過層層裝飾實現復雜組合

五、裝飾模式的優勢

  1. 靈活性:可以動態地添加或刪除功能,比繼承更靈活

  2. 避免類爆炸:不需要為每種組合創建子類

  3. 符合開閉原則:對擴展開放,對修改關閉

  4. 運行時添加功能:可以在運行時決定添加哪些裝飾

六、總結

? ? ? ?通過這個星巴克咖啡系統的例子,我們看到了裝飾模式在實際應用中的強大之處。它讓我們能夠輕松地組合各種咖啡和調料,而不需要創建大量的子類。這種模式特別適合那些需要動態、透明地添加對象功能的場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79047.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79047.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79047.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用MPI-IO并行讀寫HDF5文件

使用MPI-IO并行讀寫HDF5文件 HDF5支持通過MPI-IO進行并行讀寫,這對于大規模科學計算應用非常重要。下面我將提供C和Fortran的示例程序,展示如何使用MPI-IO并行讀寫HDF5文件。 準備工作 在使用MPI-IO的HDF5之前,需要確保: HDF5庫編譯時啟用…

七、自動化概念篇

自動化測試概念 自動化測試是把以人為驅動的測試行為轉化為機器執行的一種過程。通常,在設計了測試用例并通過評審之后,由測試人員根據測試用例中描述的過程一步步執行測試,得到實際結果與期望結果的比較。在此過程中,為了節省人…

redis cluster 的通信機制

Redis Cluster 的通信機制是其分布式架構的核心,基于 Gossip 協議 和 Cluster Bus 實現節點間狀態同步與數據協調。以下是其通信機制的核心要點: 二進制協議:數據以字節流形式編碼(如Protobuf、Thrift、MQTT、Gossip)。…

CTF web入門之文件上傳

知識點 產生文件上傳漏洞的原因 原因: 對于上傳文件的后綴名(擴展名)沒有做較為嚴格的限制 對于上傳文件的MIMETYPE(用于描述文件的類型的一種表述方法) 沒有做檢查 權限上沒有對于上傳的文件目錄設置不可執行權限,(尤其是對于shebang類型的文件) 對于web server對于上傳…

PhotoShop學習09

1.彎曲鋼筆工具 PhotoShop提供了彎曲鋼筆工具可以直觀地創建路徑,只需要對分段推拉就能夠進行修改。彎曲港幣工具位于工具面板中的鋼筆工具里,它的快捷鍵為P。 在使用前,可以把填充和描邊選為空顏色,并打開路徑選項,勾…

tsconfig.json配置不生效

說明一下我遇到的問題,這是我的配置文件代碼的 {"compilerOptions": {"module": "none","target": "ES5","outFile": "./dist/bundle.js"} } 和我想象不同的是,我編譯成 js 沒…

源代碼加密之零日攻擊

# SDC沙盒:有效防御零日攻擊的多層防護體系 在當今復雜多變的網絡安全環境中,零日攻擊已成為企業面臨的重大威脅之一。零日攻擊利用尚未被公眾發現或尚未被軟件供應商修復的漏洞進行攻擊,具有極高的隱蔽性和破壞性。SDC沙盒作為一種先進的數…

記錄一次TDSQL網關夯住故障

環境信息: TDSQL-MySQL同城雙中心集群,集中式實例,一主三副本,每個中心兩個db副本,每個中心一個VIP,V每個IP通過硬件做負載均衡指向該中心兩個proxy,操作系統為麒麟v10 arm。 故障描述&#xf…

代碼隨想錄八股訓練營完結總結

! 40天的訓練營,我總結了自己完整的八股文,后續在面試過程中可以補充 很感謝這次訓練營,真的高頻,在面試中能擊中60%以上,剩下的就靠平時的積累了。 感謝訓練營的小伙伴,很多次想偷懶&#x…

VS Code 的 .S 匯編文件里面的注釋不顯示綠色

1. 確認文件語言模式 打開 .S 文件后,查看 VS Code 右下角的狀態欄,確認當前文件的識別模式(如 Assembly、Plain Text 等)。如果顯示為 Plain Text 或其他非匯編模式: 點擊狀態欄中的語言模式(如 Plain Te…

iphone各個機型尺寸

以下是蘋果(Apple)歷代 iPhone 機型 的屏幕尺寸、分辨率及其他關鍵參數匯總(截至 2023年10月,數據基于官方發布信息): 一、標準屏 iPhone(非Pro系列) 機型屏幕尺寸(英寸…

VSCode寫java時常用的快捷鍵

首先得先安好java插件 1、獲取返回值 這里是和idea一樣的快捷鍵的,都是xxxx.var 比如現在我new一個對象 就輸入 new MbDo().var // 點擊回車即可變成下面的// MbDo mbDo new MbDo()//以此類推get方法也可獲取 mbDo.getMc().var // 點擊回車即可變成下面的 // St…

相機內外參

文章目錄 相機內參相機外參 相機的內外參是相機標定過程中確定的重要參數,用于建立圖像像素坐標與實際世界坐標之間的關系。 相機內參 定義:相機內參是描述相機內部光學和幾何特性的參數,主要包括焦距、主點坐標、像素尺度因子以及畸變系數等…

【視頻目標分割論文集】Efficient Track Anything0000

github 摘要 視頻對象分割和追蹤任意目標領域出現了強大的工具——分割任意模型 2(SAM 2)。SAM 2 實現令人印象深刻的視頻對象分割性能的關鍵組成部分包括用于幀特征提取的大型多階段圖像編碼器,以及存儲過去幀記憶上下文以輔助當前幀分割的…

CSS學習02 動態列數表格開發,解決多組數據布局與邊框重合問題

概要 在前端開發中,表格常用于展示結構化數據。當數據組的字段數量不統一時(如有的行包含 3 組數據,有的行包含 2 組或 1 組),傳統固定列數的表格會出現結構錯位、邊框重合等問題。本文通過 HTML/CSS 規范方法&#x…

Spark-core編程總結

1.reduce? 功能?:聚集RDD中的所有元素,先聚合分區內數據,再聚合分區間數據。 示例?:rdd.reduce(__) 將RDD中的所有整數相加。 2.collect? 功能?:在驅動程序中,以數組Array的形式返回數據集的所有元…

處理Long類型長度超長導致前端精度丟失問題

1,問題場景 后端返回的Long類型的數據,超10000000000000000,前端處理的時候,數據被截斷了。比如tchId: 11073477511443988481, 前端根據tchId獲取下一環節信息的時候,傳的tchId變成了11073477511443988400&…

ONVIF/RTSP/RTMP協議EasyCVR視頻匯聚平臺RTMP協議配置全攻略 | 直播推流實戰教程

在現代化的視頻管理和應急指揮系統中,RTMP協議作為一種高效的視頻流傳輸方式,正變得越來越重要。無論是安防監控、應急指揮,還是物聯網視頻融合,掌握RTMP協議的接入和配置方法,都是提升系統性能和效率的關鍵一步。 今天…

安徽京準:GPS北斗衛星時空信號安全防護裝置(授時)介紹

安徽京準:GPS北斗衛星時空信號安全防護裝置(授時)介紹 1、主要特點 ★信號加固功能: GPS/BDS單系統信號拒止情況下(包含受到GPS L1欺騙干擾、GPS L1壓制干擾、BDS B1欺騙干擾、BDS B1壓制干擾)&#xff…

探索原生JS的力量:自定義實現類似于React的useState功能

1.寫在前面 本方案特別適合希望在歷史遺留的原生JavaScript項目中實現簡單輕量級數據驅動機制的開發者。無需引入任何框架或第三方庫,即可按照此方法封裝出類似于React中useState的功能,輕松為項目添加狀態管理能力,既保持了項目的輕量性&am…