23種設計模式之裝飾者模式

深入理解裝飾者模式

  • 一、裝飾者模式簡介
    • 1.1 定義
    • 1.2 模式類型
    • 1.3 主要作用
    • 1.4 優點
    • 1.5 缺點
  • 二、模式動機
  • 三、模式結構
  • 四、 裝飾者模式的實現
    • 4.1 組件接口
    • 4.2 具體組件
    • 4.3 裝飾者抽象類
    • 4.4 具體裝飾者
    • 4.5 使用裝飾者模式
    • 4.6 輸出結果:
  • 五、 應用場景
    • 5.1 圖形用戶界面
    • 5.2 數據流處理
    • 5.3 日志功能
    • 5.4 監控和計數
  • 六、總結

在這里插入圖片描述

一、裝飾者模式簡介

1.1 定義


??裝飾者模式(Decorator Pattern)是一種結構型設計模式,它允許在運行時動態地向對象添加新的功能,而不改變其結構和實現。裝飾者模式通過組合來實現功能的擴展,它將功能劃分成單一職責的類,并在需要時動態地組合這些功能實例化對象。

??根據《設計模式:可復用面向對象軟件的基礎》一書的定義,裝飾者模式是:

動態地給對象添加一些額外的職責。就增加功能來說,裝飾者模式相比生成子類更為靈活。

1.2 模式類型


??結構型

1.3 主要作用


  1. 擴展功能:允許在運行時動態地給對象添加新的功能,而不需要修改對象的結構。這有助于遵循 OCP 原則。
  2. 靈活性和可重用性:裝飾者模式通過創建裝飾類來包裹原始對象,并在裝飾類中添加功能,這樣可以靈活組合不同的裝飾器以達到不同的功能組合,同時原始類和裝飾類都可以獨立復用。
  3. 簡化復雜度:對于有大量可選功能的對象,如果使用繼承來實現每種可能的功能組合,會導致類的數量爆炸式增長。裝飾者模式通過組合而非繼承的方式來添加功能,大大減少了類的數量,簡化了系統的復雜度。
  4. 保持接口一致性:裝飾者模式保持了被裝飾對象的接口一致,客戶端代碼可以透明地使用裝飾后的對象,無需關心是否以及如何被裝飾,這有利于代碼的維護和擴展。
  5. 易于管理對象的責任:每個裝飾者都負責單一職責,即添加特定的功能,這使得對象的責任更加清晰,便于管理和調試。

1.4 優點


  1. 靈活性高:可以在運行時任意組合裝飾者,動態地擴展對象功能。
  2. 符合單一職責原則:每個裝飾者類只負責增加一種功能,類的職責更加單一。
  3. 降低類復雜度:相比通過繼承擴展功能,裝飾者模式避免了大量的子類生成,從而減少類的復雜度。

1.5 缺點


  1. 對象數量增多:由于裝飾者和被裝飾者都是對象,這會增加系統中對象的數量,增加管理成本。
  2. 依賴過多:容易產生過多的小型對象,增加系統復雜性,理解和維護變得更加困難。

二、模式動機


裝飾者模式的主要動機是應對以下幾個問題:

  • 避免類爆炸:通過繼承添加新功能會導致子類數量激增,維護起來十分困難。
  • 靈活組合功能:繼承的組合方式是靜態的,不夠靈活。裝飾者模式允許動態地組合功能。
  • 單一職責原則:通過將功能分解到不同的裝飾類中,裝飾者模式使每個類的職責更加單一,代碼更易讀易維護。

三、模式結構

在這里插入圖片描述

裝飾者模式通常涉及以下幾個角色:

  • Component(抽象組件):定義一個對象接口,可以給這些對象動態地添加職責。
  • ConcreteComponent(具體組件):實現 Component 接口的具體對象,可以給這些對象添加一些職責。
  • Decorator(裝飾者抽象類):繼承 Component 接口,通常持有一個 Component 對象的引用,并定義一個與 Component 接口一致的接口。
  • ConcreteDecorator(具體裝飾者):擴展 Decorator 類的具體裝飾者,負責向組件添加新的職責。

四、 裝飾者模式的實現


??我們將以一個具體的咖啡示例來介紹裝飾者模式的實現。在這個例子中,我們有一個基本的咖啡對象,可以動態地添加不同的配料(如牛奶和糖)。

4.1 組件接口

// Java實現
public interface Coffee {double cost();String getDescription();
}

4.2 具體組件

public class SimpleCoffee implements Coffee {public double cost() {return 5.0;}public String getDescription() {return "Simple Coffee";}
}

4.3 裝飾者抽象類

public abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}public double cost() {return coffee.cost();}public String getDescription() {return coffee.getDescription();}
}

4.4 具體裝飾者

public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}public double cost() {return super.cost() + 1.5;}public String getDescription() {return super.getDescription() + ", Milk";}
}public class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}public double cost() {return super.cost() + 0.5;}public String getDescription() {return super.getDescription() + ", Sugar";}
}

4.5 使用裝飾者模式

public class CoffeeShop {public static void main(String[] args) {Coffee coffee = new SimpleCoffee();System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());coffee = new MilkDecorator(coffee);System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());coffee = new SugarDecorator(coffee);System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());}
}

4.6 輸出結果:

Simple Coffee Cost: $5.0
Simple Coffee, Milk Cost: $6.5
Simple Coffee, Milk, Sugar Cost: $7.0

五、 應用場景

在這里插入圖片描述

5.1 圖形用戶界面


??在圖形用戶界面(GUI)框架中,裝飾者模式廣泛應用于實現各種控件的裝飾功能。控件如按鈕、文本框等可以用不同的裝飾者類裝飾來添加多種新功能,如滾動條、邊框等。例如,Java Swing框架中的JComponent類就是使用類似裝飾者模式的理念實現的。

5.2 數據流處理


??在數據流處理框架中,輸入輸出流是裝飾者模式的另一個經典應用。JavaI/O流設計就是實現裝飾者模式的一個優秀示例,如FileInputStreamBufferedInputStreamDataInputStream等通過裝飾者模式組合,實現了靈活而強大的數據流操作功能。

5.3 日志功能


??日志記錄功能的實現也是裝飾者模式的理想應用場景。例如,傳統的日志記錄器Logger可以通過裝飾者模式添加不同的日志處理和記錄策略,如格式化日志、輸出到文件、發送電子郵件等。

5.4 監控和計數


??在監控系統中,可以動態地為程序添加計數器、性能監控器等功能,以增強對系統運行狀態的了解。

六、總結

??裝飾者模式是一種強大的設計模式,它提供了一種靈活、可擴展的方式來動態地為對象添加新功能。通過這一模式,我們可以在不修改已有類代碼的情況下,靈活地擴展系統功能,符合開閉原則單一職責原則。無論是在GUI編程中、日志功能增強,還是在數據流處理以及監控系統中,裝飾者模式都能發揮重要作用。

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

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

相關文章

排序(堆排序、快速排序、歸并排序)-->深度剖析(二)

前言 前面介紹了冒泡排序、選擇排序、插入排序、希爾排序,作為排序中經常用到了算法,還有堆排序、快速排序、歸并排序 堆排序(HeaSort) 堆排序的概念 堆排序是一種有效的排序算法,它利用了完全二叉樹的特性。在C語言…

復分析——第9章——橢圓函數導論(E.M. Stein R. Shakarchi)

第 9 章 橢圓函數導論 (An Introduction to Elliptic Functions) The form that Jacobi had given to the theory of elliptic functions was far from perfection; its flaws are obvious. At the base we find three fundamental functions sn, cn and dn. These functio…

商湯上海AI實驗室聯合發布:自動駕駛全棧式高精度標定工具箱(含車、IMU、相機、激光雷達等的標定)

前言 在自動駕駛技術飛速發展的今天,傳感器的精確標定對于確保系統性能至關重要。SensorsCalibration,一個專為自動駕駛車輛設計的標定工具箱,提供了一套全面的解決方案,用于校準包括IMU、激光雷達、攝像頭和雷達在內的多種傳感器…

基于Java平價平價汽車租賃系統設計和實現(源碼+LW+部署講解)

💗博主介紹:?全網粉絲10W,CSDN作者、博客專家、全棧領域優質創作者,博客之星、平臺優質作者、專注于Java、小程序技術領域和畢業項目實戰?💗 🌟文末獲取源碼數據庫🌟 感興趣的可以先收藏起來,…

【python】使用conda管理python項目:conda管理不同項目環境,pip下載最新的包

文章目錄 一. python包管理概述1. miniforge、Miniconda與Anaconda2. conda與pip的區別是什么?3. pip與conda配合使用 二. 使用conda管理不同py環境1. 創建一個環境2. 解決沖突 三. 命令合集1. conda1.1. 常用1.2. 環境管理1.3. 分享環境1.4. 包管理 2. 依賴沒有在c…

《RepViT Revisiting Mobile CNN From ViT Perspective》

期刊:CVPR 年份:2024 代碼:http://https: //github.com/THU-MIG/RepViT 摘要 最近,與輕量級卷積神經網絡(CNN)相比,輕量級視覺Transformer(ViTs)在資源受限的移動設備上表現出了更高的性能和更低的延遲。研究人員已…

無法訪問指向的web服務器(或虛擬主機)的目錄,請檢查網絡設置

微信公眾平臺,進行業務域名、JS接口安全域名、網頁授權域名配置時,遇到的問題中有:無法訪問指向的web服務器(或虛擬主機)的目錄,請檢查網絡設置,這里簡單記錄一下處理過程。 關于這個問題首先保證下載…

SHELL腳本學習(十四)gawk進階

一、使用變量 gawk支持兩種變量 內建變量自定義變量 1.1 內建變量 1.1.1 字段和記錄分隔符變量 數據字段變量允許使用美元符號 $ 和 位置來引用對應的字段。 $1 對應第一個數據字段,$2對應第二個數據字段,以此類推。 數據字段用字段分隔符劃定。默…

【基于R語言群體遺傳學】-1-哈代溫伯格基因型比例

前言 群體遺傳學是研究生物群體中基因的分布、基因頻率和基因型頻率的維持和變化的學科。它不僅探討遺傳病的發病頻率和遺傳方式,還研究基因頻率和變化的規律,為預防、監測和治療遺傳病提供重要信息。R語言作為一種強大的統計分析工具,在群體…

mybatis實現多表查詢

mybatis高級查詢【掌握】 1、準備工作 【1】包結構 創建java項目,導入jar包和log4j日志配置文件以及連接數據庫的配置文件; 【2】導入SQL腳本 運行資料中的sql腳本:mybatis.sql 【3】創建實體來包,導入資料中的pojo 【4】User…

TypeScript Project References npm 包構建小實踐

npm 包輸出 es/cjs 產物 在開發一個 npm 包時,通常需要同時輸出 ES 模塊和 CommonJS 模塊的產物供不同的構建進行使用。在只使用tsc進行產物編譯的情況下,我們通常可以通過配置兩個獨立的 tsconfig.json 配置文件,并在一個 npm script 中 執…

kubesphere自定義流水線基礎鏡像

背景 需求:在流水線基礎pod中使用python和jinja2模塊來動態渲染部署文件 由于ks提供的基礎鏡像無法滿足以上需求,在ks提供的maven鏡像的基礎上實現 實施 制作鏡像&并推送到private image repo FROM kubesphere/builder-maven:v3.2.0 RUN sed -i…

7.1作業

1.思維導圖 2.在堆區申請兩個長度為32的空間,實現兩個字符串的比較【非庫函數實現】 (1)定義函數,在對區申請空間 兩個申請,主函數需要調用2次 (2)定義函數,實現字符串的輸入 void input(char *p) (3)調用函數實現字符串比較…

BUT000增強字段BAPI結構激活出錯(BUPA_CENTRAL_CI_CHANGE)

導語:BP主數據增強字段,需要使用BAPI:BUPA_CENTRAL_CI_CHANGE進行值寫入,但是在SAP 2023以后的版本,激活會出錯,原因是因為SAP的一個結構同時包含了BUS00_EEW以及BUS00_EEWX兩個結構,導致結構字…

Spring Security 認證流程

Spring Scurity是spring生態下用于認證和授權的框架,具有高度的靈活性和可擴展行,本節主要對Spring Security的認證過程中進行概括性的介紹,主要介紹在該過程中,會涉及到哪些組件以及每個組件所承擔的職責,希望大家可以…

Elasticsearch 配置說明

# ---------------------------------- Cluster ----------------------------------- cluster.name: yh-es # es名稱 # ------------------------------------ Node ------------------------------------ node.name: xibo-es node.master: true node.da…

電腦錄音軟件哪個好?7款錄制音頻工具大盤點,趕快學起來!(2024)

也許你渴望提取你最喜歡的節目的背景音樂,或者你希望錄制自己的聲音制作教程。如果是這樣,你就需要一款優秀的電腦錄音軟件,來幫助你捕捉任何你想要的聲音,而且不會損失音質。目前市場上存在著大量的錄制音頻工具,面對…

鎖相環相位噪聲仿真代碼-匯總

24小時自動發貨 所設計的壓控振蕩器輸入電壓為0.625V時,輸出大致為500Mhz;輸入電壓為1.559時,輸出電壓大致為1Ghz 1.文件夾里面各個文件作用(包括參考書PLL PHASE NOISE ANALYSIS、lee的射頻微電子、以及前人留下的matlab文件還有…

ModStart:開源免費的PHP企業網站開發建設管理系統

大家好!今天我要給大家介紹一款超級強大的開源工具——ModStart,它基于Laravel框架,是PHP企業網站開發建設的絕佳選擇! 為什么選擇ModStart? 模塊化設計:ModStart采用模塊化設計,內置了眾多基…