每天一個設計模式 -9 裝飾者模式

来源:http://www.cnblogs.com/xiemubg/archive/2017/04/23/6753811.html
-Advertisement-
Play Games

每天一個設計模式 -9 裝飾者模式 一、現實 使用繼承不總能夠實現最有彈性和最好維護的設計。 利用組合和委托可以在運行時具有繼承行為的效果。 利用繼承設計子類的行為,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行為。 利用組合的做法擴展對象的行為,就可以在運行時動態地進行擴展。 二、認識裝飾 ...


每天一個設計模式 -9 裝飾者模式

一、現實

  • 使用繼承不總能夠實現最有彈性和最好維護的設計。
  • 利用組合和委托可以在運行時具有繼承行為的效果。

利用繼承設計子類的行為,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行為。

利用組合的做法擴展對象的行為,就可以在運行時動態地進行擴展。

二、認識裝飾者模式

角色:

  • 裝飾者
  • 組件

舉例:

給咖啡添加調料(咖啡(組件或被裝飾對象),調料(裝飾者)種類很多。咖啡,調料需要付費)並能算出需要付款的總費用,用圖形表示:

  1. 裝飾者和被裝飾對象有相同的超類型。
  2. 可以用一個或多個裝飾者包裝一個對象。
  3. 裝飾者和被裝飾對象有相同的超類型,所以在任何需要原始對象(被包裝的)的場合,可以用裝飾過的對象代替它。
  4. 裝飾者可以在所委托被裝飾者的行為之前與/或之後,加上自己的行為,已達到特定的目的。
  5. 對象可以在任何時候被裝飾,所以可以在運行是動態地,不限量的用你喜歡的裝飾者來裝飾對象。

三、定義裝飾者模式

定義:裝飾者模式動態的將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案

通用的類圖:

對這個類圖進行改造,完成上面的例子:

四、源代碼

抽象類 Coffee:一個description欄位,一個抽象方法cost,一個有預設實現的getDescription()方法

public abstract class Coffee {

     String description = "未知的咖啡";

    public Coffee(){

    }

    public void finalize() throws Throwable {

    }

    public abstract double cost();

    public String getDescription(){
        return description;
    }

}
Coffee

四個具體的Coffee類Coffee1,Coffee2...,繼承自Coffee,實現抽象方法cost()

public class Coffee1 extends Coffee {

    public Coffee1(){
        description = "咖啡1";
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public double cost(){
        return 10;
    }
}
public class Coffee2 extends Coffee {

    public Coffee2(){
        description = "咖啡2";
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public double cost(){
        return 20;
    }
}
public class Coffee3 extends Coffee {

    public Coffee3(){
        description = "咖啡3";
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public double cost(){
        return 30;
    }
}
public class Coffee4 extends Coffee {

    public Coffee4(){
        description = "咖啡4";
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public double cost(){
        return 20;
    }
}
Coffee的具體類

抽象類 CondimentDectorator:繼承自Coffee 一個抽象方法getDescription(),強制子類重寫

public abstract class CondimentDecorator extends Coffee {

    public Coffee m_Coffee;

    public CondimentDecorator(){

    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public abstract String getDescription();
}
CondimentDectorator

三個具體的CondimentDectorator,Condiment1...,繼承自CondimentDectorator,實現抽象方法getDescription()

public class Condiment1 extends CondimentDecorator {

    public Condiment1(Coffee coffee){
        m_Coffee = coffee;
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public double cost(){
        //計算自己和被裝飾的對象的價格
        return m_Coffee.cost()+0.9;
    }

    public String getDescription(){
        return m_Coffee.getDescription()+",Condiment1";
    }
}
//----------------------------------------------------------------------------
public class Condiment2 extends CondimentDecorator {

    public Condiment2(Coffee coffee){
        m_Coffee = coffee;
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public double cost(){
        return m_Coffee.cost()+0.7;
    }

    public String getDescription(){
        return m_Coffee.getDescription()+",Condiment2";
    }
}
//---------------------------------------------------------------------------
public class Condiment3 extends CondimentDecorator {

    public Condiment3(Coffee coffee){
        m_Coffee = coffee;
    }

    public void finalize() throws Throwable {
        super.finalize();
    }

    public double cost(){
        return m_Coffee.cost()+0.5;
    }

    public String getDescription(){
        return m_Coffee.getDescription()+",Condiment3";
    }
}
CondimentDectorator具體類

五、總結

從這次學習中能看出一些OO原則:

  • 封裝變化(Coffee封裝了變化)
  • 多用組合,少用繼承(繼承可能會變得死板,組合達到擴展則很靈活)
  • 針對藉口編程,不針對實現編程(抽象類)
  • 對擴展開放,對修改關閉
  • 依賴抽象

轉載註明出處:http://www.cnblogs.com/xiemubg/p/6753811.html


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

-Advertisement-
Play Games
更多相關文章
  • 概述: GOF定義:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。 在軟體開發特別是DSL開發中常常需要使用一些相對較複雜的業務語言,如果業務語言使用頻率足夠高,且使用普通的編程模式來實現會導致非常複雜的變化,那麼就可以考慮使用解釋器模式構建一個解釋 ...
  • 讀完了這本書,收穫很多,對程式設計有了很多新的理解。將每章模式的大概要點做了些筆記以備查閱,一些設計模式書讀完也對其瞭解得不是很透徹,需要以後在實踐中來不斷地加深理解吧。讀書過程中用Java跟著實踐了些部分模式的代碼上傳到了 "https://github.com/wanghaoxi3000/des ...
  • 1、使用Eclipse 建立Maven項目(webapp OR quickstart) 2、配置Maven,如下: 3、建立啟動Application 4、編輯Controller 5、通過application.properties對項目進行配置 項目文件佈局如下: 啟動Application程式 ...
  • 現象: 同事負責的項目轉到我的頭上,整理服務過程中發現了隊列的積壓問題。 為了搞清楚積壓的嚴重程度, 對隊列任務數每分鐘進行一次採樣,生成一個走勢圖, 隊列積壓情況一目瞭然,非常嚴重。 分析: 聽了同事對系統的介紹,猜測是mongo性能影響了處理效率,於是針對mongo進行分析 1. 使用mongo ...
  • 1. 前言 2. 所謂習慣認知 3. 開門見山的萬金油 第1條:抽象類設計註重對象性,介面設計註重服務性 第2條:更近的抽象類,更遠的介面 第3條:子類間有關係時考慮用抽象類,沒有關係時一定要用介面 第4條:版本迭代中優先考慮使用抽象類而不是介面 4. 設計是個性的妥協 5. 參考資料 1. 前言 ...
  • 程式優化是用於消除程式中大量的if else這種判斷語句 ...
  • 歷時兩個多月的時間,終於把effective c++又複習了一遍,比較慢,看的是英文版,之前看的時候做過一些筆記,但不夠詳細,這次筆者是從頭到尾的翻譯了一遍,加了一些標題,先記錄到word裡面,然後發佈到博客園上。這麼做是為了方便查閱,複習C++,同時練習英文,希望這些帖子也能夠對大家有所幫助。 有 ...
  • 什麼是觀察者模式 舉個例子來簡單說明下這個模式:假如現在你在一家報社訂閱了報紙,每當有新的期刊,那麼他們就會把報紙送到你家,如果你什麼時候不想看這一期刊的時候,你就可以取消訂閱,那麼這時候他們就不會將報紙送到你家了。這其實就是利用了觀察者模式,先給出兩個基本概念:主題,就相當於被觀察的對象,這裡指的 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...