設計模式之裝飾者模式(二)

来源:https://www.cnblogs.com/dimple91/archive/2019/04/08/10669054.html
-Advertisement-
Play Games

歡迎大家的不嫌棄,繼續和我一起學習設計模式。上一篇已經把裝飾者模式的類圖有了一個整體的出來,末尾說的去想想實現的代碼,你實踐了嗎?是什麼原因讓你實踐了呢?又是什麼原因讓你沒有動手呢?沒動手,可能是思路還不夠明確是嗎? 接下來,我們繼續學習。通過代碼實現的方式,來搞定裝飾者模式。 寫下代碼 動手的時候 ...


歡迎大家的不嫌棄,繼續和我一起學習設計模式。上一篇已經把裝飾者模式的類圖有了一個整體的出來,末尾說的去想想實現的代碼,你實踐了嗎?是什麼原因讓你實踐了呢?又是什麼原因讓你沒有動手呢?沒動手,可能是思路還不夠明確是嗎?

接下來,我們繼續學習。通過代碼實現的方式,來搞定裝飾者模式。

寫下代碼

動手的時候來啦,我們先從Beverage類下手。這不需要修改原有的設計,如下所示:

/**
 * 
 * @Description: Beverage是一個抽象類,有兩個方法:getDescription()以及cost()
 * @author:XuYue
 */
public abstract class Beverage {
    String description = "Unknown Beverage";
    
    // getDescription()已經在此實現了,但是cost()必須在子類中實現
    public String getDescription() {
        return description;
    }
    
    public abstract double cost();
}

然後我們繼續實現Condiment(調料)抽象類,也就是裝飾者類:

/**
 * 
 * @Description: 必須讓CondimentDecorator能夠取代Beverage,所以將CondimentDecorator擴展自Beverage類
 */
public abstract class CondimentDecorator extends Beverage {
    // 所有的調料裝飾者都必須重新實現getDescription()方法,稍後說明原因
    public abstract String getDescription();
}

寫飲料的代碼

有了上面的基礎,即已經有了基類,那我們就可以愉快的把飲料類實現了。先從濃縮咖啡(Espresso)開始吧。在這,我們需要實現cost()方法以及將描述設置清楚。其他類,在代碼里表現,就不在文中體現啦。

/**
 * 
 * @Description:首先,讓Espresso擴展自Beverage類,因為Espresso是一種飲料
 * @author:XuYue
 */
public class Espresso extends Beverage {

    public Espresso() {
        // 為了要設置飲料的描述,我們寫了一個構造器,description繼承自Beverage
        description = "Espresso";
    }
    
    // 需要計算Espresso的價錢
    @Override
    public double cost() {
        return 1.99;
    }

}

寫調料代碼

還記得上篇中的類圖嗎,根據類圖我們已經完成了抽象組件(Beverage),有了具體組件(HoustBlend),也有了抽象裝飾者(CondimentDecorator)。那麼,就差實現具體的裝飾者了,也就是我們的調料。這裡是列舉Mocha,其他的自行實現哦。小編提供的代碼里已經實現啦, 感興趣的小伙伴,可以寫完和小編的PK下。

/**
 * 
 * @Description:
 * 摩卡是一個裝飾者,所以讓它擴展自CondimentDecorator
 * CondimentDecorator擴展自Beverage
 * @author:XuYue
 */
public class Mocha extends CondimentDecorator {

    Beverage beverage;
    
    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + " , Mocha";
    }

    @Override
    public double cost() {
        return 0.20 + beverage.cost();
    }

}

供應咖啡

恭喜你,經歷過之前的準備,是時候坐下來休息休息,點一杯咖啡享受下人生啦。來看看你的裝飾者模式設計出來的系統吧。

寫之前,我們先看看雙倍摩卡咖啡的是怎麼裝飾的吧。其實就是上一篇中的單倍摩卡,再加一層摩卡的裝飾類即可,是不是很神奇呢。

public class StarbuzzCoffee {

    public static void main(String[] args) {
        // 訂一杯Espresso,不需要調料
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());
        
        // 訂一杯雙倍Mocha加Whip的DarkRoast()咖啡
        Beverage beverage2 = new DarkRoast();
        // 用Mocha裝飾它
        beverage2 = new Mocha(beverage2);
        // 用第二個Mocha裝飾它
        beverage2 = new Mocha(beverage2);
        // 用Whip裝飾它
        beverage2 = new Whip(beverage2);
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
        
        // 訂一杯調料為Soy、Mocha、Whip的HouseBlend咖啡
        Beverage beverage3 = new HouseBlend();
        beverage3 = new Soy(beverage3);
        beverage3 = new Mocha(beverage3);
        beverage3 = new Whip(beverage3);
        System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
        
    }
}

// 輸出結果
Espresso $1.99
Dark Roast Coffee , Mocha , Mocha , Whip $1.49
House Blend Coffee , Soy , Mocha , Whip $1.34

目前為止,我們已經把上篇遺留下來的類圖轉換成了代碼實現出來。當我們在後面介紹到工廠和生成器模式的時候,將會有更好的方式建立被裝飾者對象。所以,儘管現在的裝飾者模式存在部分缺陷,但不妨礙我們對這個模式的學習,後續的增加,只是對模式有更加深刻的認知。

所以,這次的內容就先到這裡。下一篇,我們針對性的對現有JDK中的裝飾者模式舉個例子,並對裝飾者模式做出總結。

留個小習題,在這次講的過程中我們是加了調料, 那咖啡廳里現在都會有杯子的大小,小杯、中杯、大杯,並收取相應的價錢,該如何編寫呢?先拋個磚,我們在Beverage類中加上getSize()和setSize()。下次小編會給出答案噢。

PS:代碼已經上傳,需要查看的朋友點擊此處HeadFirstDesign

推薦閱讀

設計模式之裝飾者模式(一)

愛生活,愛學習,愛感悟,愛挨踢


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JavaScript_01簡介,基本語法,運算符,和java語言進行對比總結 ...
  • 1,element 表格嵌入CheckBox 效果圖如下: 2,element結合checkBox實現單選效果如下: html代碼: js代碼: ...
  • "use strict": 1、它是 ES5 引入的一條指令,指令不是語句,但非常接近於語句 2、不包含任何語言的關鍵字,指令僅僅是一個包含一個特殊字元串直接量的表達式。對於那些沒有實現 ES5 的 JavaScript 解釋器來說,它只是一條沒有副作用的表達式語句 3、只能出現在腳本代碼的開始或函 ...
  • HTML部分 js部分 ...
  • 接手項目之後,在安裝依賴後,再npm start的過程中報錯./node_modules/history/esm/history.js Module not found: Can't resolve '@babel/runtime/helpers/esm/extends' ...
  • 最近一個星期準備學習一下angular前端框架,因為之前在學習abp框架的時候,都要求前端要掌握angular,所以不得不回來惡補一下了,學習的過程有時間的話會記錄在這裡,方便以後複習。 閑言少敘,下麵來介紹開發環境搭建的步驟: 開發環境搭建 1.安裝node和npm(其實只需要安裝node,因為n ...
  • 前言: 相信大家都打開過層級很多很多的文件夾。如果把第一個文件夾看作是樹的根節點的話,下麵的子文件夾就可以看作一個子節點。不過最終我們尋找的還是文件夾中的文件,文件可以看做是葉子節點。下麵我們介紹一種模式,與這種樹級結構息息相關。當然,今天的主角是HashMap。接下來我們一起來看HashMap中到 ...
  • 一、引言 我們都知道,資料庫連接是很珍貴的資源,頻繁的開關資料庫連接是非常浪費伺服器的CPU資源以及記憶體的,所以我們一般都是使用資料庫連接池來解決這一問題,即創造一堆等待被使用的連接,等到用的時候就從池裡取一個,不用了再放回去,資料庫連接在整個應用啟動期間,幾乎是不關閉的,除非是超過了最大閑置時間。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...