結合JDK源碼看設計模式——裝飾者模式

来源:https://www.cnblogs.com/Cubemen/archive/2019/04/05/10658183.html
-Advertisement-
Play Games

定義 在不改變原有對象的基礎之上,將功能附加到對象上 適用場景 詳解 在看到定義的時候,可能很多人會想,這不就是繼承嗎?的確很像,不過是比繼承更加有彈性的替代方案。就像原型模式和new之間的關係一樣,有區別,但是區別又不是特別大。裝飾者一個很重要的詞就是動態,他可以靈活的選擇要這個功能還是不要。在裝 ...


定義

  在不改變原有對象的基礎之上,將功能附加到對象上

適用場景

  1. 擴展一個類的功能
  2. 動態的給對象增加功能,當功能不需要的時候能夠動態刪除

詳解

  在看到定義的時候,可能很多人會想,這不就是繼承嗎?的確很像,不過是比繼承更加有彈性的替代方案。就像原型模式和new之間的關係一樣,有區別,但是區別又不是特別大。裝飾者一個很重要的詞就是動態,他可以靈活的選擇要這個功能還是不要。在裝飾者中要有四個角色:抽象的實體類,具體的實體類,抽象的裝飾者,具體的裝飾者。下麵畫一個大致的UML圖

  實體類創建之後,如果想擴展實體類那麼一般的想法是繼承,當然繼承也是其中方法之一。上面由UML圖就可以看出,在裝飾者模式下,我們可以通過裝飾類下的擴展功能實現對抽象實體類的包裝。當我們需要擴展功能就多加一個擴展功能,不需要擴展功能就不用添加,是一個很動態的擴展方式。下麵具體看代碼解析。

抽象實體類

public abstract class abstractCake {
    protected abstract String getCake();
    protected abstract int cost();

}

實體類

public class cake extends abstractCake{
    @Override
    protected String getCake() {
        return "蛋糕";
    }

    @Override
    protected int cost() {
        return 100;
    }
}

抽象裝飾類(可以抽象也可以不抽象)

public class AbstractDecorator extends abstractCake {
    private abstractCake abstractcake;

    public AbstractDecorator(abstractCake abstractcake) {
        this.abstractcake = abstractcake;
    }



    @Override
    protected String getCake() {
        return this.abstractcake.getCake();
    }

    @Override
    protected int cost() {
        return this.abstractcake.cost();
    }
}

擴展功能1

public class FruitDecorator extends AbstractDecorator {
    public FruitDecorator(abstractCake abstractcake) {
        super(abstractcake);
    }



    @Override
    protected String getCake() {
        return super.getCake()+" 加一層水果";
    }

    @Override
    protected int cost() {
        return super.cost()+20;
    }
}

擴展功能2

public class SugerDecorator extends AbstractDecorator{
    public SugerDecorator(abstractCake abstractcake) {
        super(abstractcake);
    }



    @Override
    protected String getCake() {
        return super.getCake()+" 多加糖";
    }

    @Override
    protected int cost() {
        return super.cost()+10;
    }
}

測試類

public class Test {
    public static void main(String[] args) {

        abstractCake ac=new cake();
        ac=new FruitDecorator(ac);
        ac=new SugerDecorator(ac);
        System.out.println(ac.getCake());

    }
}

結果

具體的記憶體圖

  可以很清楚的看見ac這個抽象類下麵一層層包著實體類,解析的時候每一層的包裝類的getCake()方法都會送回給抽象實體類,而我的getCake()方法實現的是字元串增加。後面如果我還需要一層水果,那麼我就多裝飾一次。如果用繼承實現,那麼我要兩層水果,不要糖,那麼我就還需要再定義一個實現兩層水果的子類,而裝飾者模式就只需要修改客戶端的ac類實現就行。在JDK中裝飾者模式用的最出名的莫過於IO流了,以InputStream為例子。下麵是UML圖

 

  這就是典型的裝飾者。平常我們只需要FileInputStream來讀取文件,當我們有一些特殊功能需要,如:BufferedInputStream(完成了緩存功能,使讀取文件速度大大提升)和DataInputStream(把byte轉換成Java基本數據類型)我們就可以裝飾一下InputStream,即靈活又方便。這樣使得我們對FileInputStream流的處理更能達到我們想要的預期。當你理解了裝飾者模式,我推薦你看這篇博客。這樣你就能很好的理解IO流的操作。

總結

  裝飾者模式是一個比繼承更加靈活的擴展方式,要記住裝飾者模式必不可少的4個類:抽象的實體類,具體的實體類,抽象的裝飾者,具體的裝飾者。再結合上面推薦的博客,我相信你不但能理解裝飾者,還能更加清晰的理解JDK中的IO流

 


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

-Advertisement-
Play Games
更多相關文章
  • emmmmm.....標題我就覺得起的很變態。閑話不多說,先說出現的背景吧~~。 因為業務上的需求,跟一個硬體對接,要做大屏展示大廳客流熱力圖分佈(背景圖是客戶那邊給的)。然後這個機子傳過來的數據就可能20來條。如果用最新的echarts4來做,但是數據太小不足以畫出圖來,但是如果數據太大傳輸也是一 ...
  • "官方文檔" 前言 所謂視頻上傳,是指開發者或其用戶將視頻文件上傳到點播的視頻存儲中,以便進行視頻處理、分發等。 一、簡介 騰訊雲點播支持如下幾種視頻上傳方式: 1. 控制臺上傳:在點播控制臺上進行操作,將本地視頻上傳到雲點播,適用於直接管理少量視頻的場景,具有方便快捷、無技術門檻的優點; 2. 服 ...
  • 數組方法: 1、Array.join([param]) 方法:將數組中所有的元素都轉換為字元串並連接起來,通過字元 param 連接,預設使用逗號,返回最後生成的字元串 2、Array.reverse() 方法:將數組中的元素顛倒順序(在原數組中重新排列它們),返回逆序數組 3、Array.sort ...
  • 一、HTML5簡介 HTML 5 的第一份正式草案已於2008年1月22日公佈。HTML5 仍處於完善之中。然而,大部分現代瀏覽器已經具備了某些 HTML5 支持。 2014年10月29日,萬維網聯盟宣佈,經過幾乎8年的艱辛努力,HTML5標準規範終於最終制定完成了,並已公開發佈。 HTML5不僅僅 ...
  • 一. 提前準備工作 1.Node.js環境 2.Windows10 3.npm(前端包管理工具) 4.webpack(前端資源載入/打包工具) 二. 開始安裝 1.。下載並安裝Node.js 下載地址:https://nodejs.org/en/download/ 2.在cmd中查看node.js是 ...
  • 基本實現: 解析GET參數: 解析POST: ...
  • 原生 JavaScript 實現掃雷 完整思路分析,代碼實現。 ...
  • 這是我第一次寫博客,請多指教! vector是一種向量容器,說白了就是可以改變大小的數組。 vector是一個模板類,如果直接這樣會報錯: 1 vector a; //報錯,因為要指定模板。 需要像這樣: 那麼,什麼是 模板 呢? 模板是C++支持參數化多態的工具,使用模板可以使用戶為類或者函數聲明 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...