裝飾器模式:如何用Java打扮一個對象?

  • 引言
    • 裝飾器模式
    • 具體實例
      • 共有接口類
      • 具體被裝飾類
      • 抽象裝飾器類
      • 具體裝飾器類
    • 測試
    • 裝飾器模式的實際應用
      • Java I/O 體系
      • 游戲開發中的角色裝備系統
  • 總結

引言

在生活中,我們都知道一句話,“人靠衣裝馬靠鞍”,如果想要讓自己在別人眼里看起來更加好看,更加豐富多彩,就得要學會打扮自己,為自己化妝,為自己穿好看的衣服,學會了打扮的本領,那么我們就可以輕松應對不同場合的需求。無論是日常通勤的簡約風,還是晚宴的華麗造型,我們只需在“基礎自我”上疊加不同的裝飾元素,而無需改變本質——這種靈活性和可擴展性,恰恰是裝飾器模式(Decorator Pattern) 在軟件設計中的精髓。
想象一下,我們在實際生活中,是不是如果當前的臉上瑕疵較多,就使用素顏霜遮蓋一下,當前的皮膚太黑,也可以通過化妝技術變白。穿衣更是如此,我們可以選擇穿簡約風格的衣服,在得知今晚要參加晚宴后,還可以換上一套隆重的禮服。這些操作都不需要我們變成一個新的人(繼承的方法),只需要我們使用一下化妝或者是換裝的方法就可以(裝飾器的方法)。
本文通過對一個男孩打扮和換裝的例子,來深入了解裝飾器模式。

裝飾器模式

裝飾器模式是一個結構性設計模式,允許在不修改原有類的情況下,為對象動態添加新功能,而不會影響其他對象。通過將對象放入包含行為的特殊封裝對象中來為原對象綁定新的行為。針對目標方法進行增強,提供新的功能或者額外的功能。也就是例子中的我們把需要打扮的男孩放到化妝臺前或者是衣柜前,然后這個男孩回來的時候就是一個打扮過的了,比原來更加豐富多彩。
首先看一下裝飾器模式的四大核心組件:
在這里插入圖片描述
Component: 所有可以被裝飾的類要繼承的接口,同時,裝飾器類也要繼承該接口,這樣可以保證裝飾前的對象和經過裝飾后返回的對象是同一個類型。
ConcreteComponent: 具體要裝飾的類,實現Component接口,實現被裝飾前的方法。
AbstractDecorator: 抽象裝飾器類,同樣實現AbstractDecorator接口,為什么要有這個抽象類呢?其實就是可以在這個抽象類中提前把被裝飾的對象原始的功能實現,這樣具體的裝飾器類就不用每個都重復實現原本被裝飾前的對象的功能了,只需要關注如何裝飾它。
ConcreteDecorator: 具體的裝飾器類,繼承抽象裝飾器類,它需要裝飾的那個對象的原來的方法已經在抽象裝飾器中實現了,所以這個類只需要關注需要對被裝飾的類做出哪些裝飾就行了。

具體實例

本文設計的例子是對一個男孩進行打扮,通過化妝臺(化妝裝飾器 MakeupDecorator)和衣帽間(DressupSimpleDecoratorDressupGrandDecorator )對男孩進行兩次裝飾,最終男孩原本的模樣(方法)變成裝飾后的模樣。

共有接口類

所有可以被裝飾的類都要繼承這個接口。

//可以進行裝飾需要滿足的接口
interface PersonComponent{public String getFace();public String getColor();public String getDressed();
}

具體被裝飾類

男孩需要被打扮,所以它實現上面的WaitForDecorator接口。

//等待被裝飾的類
class Boy implements PersonComponent{String face;String color;String dress;@Overridepublic String getFace() {return "ugly";}@Overridepublic String getColor() {return "black";}@Overridepublic String getDressed() {return "naked";}
}

抽象裝飾器類

所有的具體裝飾器類都要繼承該接口,可以避免重復的代碼多次編寫,將需要被裝飾的對象在這個抽象裝飾器類中將原本的功能實現一遍,這樣具體裝飾器類就只需要關注具體需要裝飾的功能了。

//裝飾器基類
abstract class PersonDecorator implements PersonComponent{private People people;public PeopleDecorator(People people){this.people=people;}@Overridepublic String getFace(){return people.getFace();}@Overridepublic String getColor(){return people.getColor();}@Overridepublic String getDressed(){return people.getDressed();}
}

具體裝飾器類

化妝裝飾器:

class MakeupDecorator extends PersonDecorator{public MakeupDecorator(People people) {super(people);}@Overridepublic String getFace(){return "make ugly to pretty";}@Overridepublic String getColor(){return "make black to white";}
}

簡約風衣著裝飾器:

class DressupSimpleDecorator extends PersonDecorator{public DressupSimpleDecorator(People people) {super(people);}public String getDressed(){return "wearing simple cloth";}
}

宴會衣著裝飾器:


class DressupGrandDecorator extends PersonDecorator{public DressupGrandDecorator(People people) {super(people);}public String getDressed(){return "wearing grand cloth";}}

測試

public static void main(String[] args) {PersonComponent boy =new Boy();//男孩先穿了簡約衣服打算出門吃海底撈boy = new DressupSimpleDecorator(boy);//男孩簡單地化了個妝boy = new MakeupDecorator(boy);//男孩突然被通知需要參加一場宴會,就換上了華麗的衣服。boy = new DressupGrandDecorator(boy);System.out.println(boy.getColor());System.out.println(boy.getFace());System.out.println(boy.getDressed());}

運行結果如下:

make black to white
make ugly to pretty
wearing grand cloth

可以看見男孩化了妝并且變得漂亮了,最后穿上的是后來穿的華麗衣服。

裝飾器模式的實際應用

下面列舉了幾個典型的應用場景:

Java I/O 體系

Java 的 I/O 類庫大量使用了裝飾器模式,例如 BufferedReader、InputStreamReader、FileInputStream 等,允許開發者通過不同的裝飾器動態增強流的功能。

BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("data.txt")));

這里,BufferedReader 作為裝飾器,增強了 InputStreamReader,提供了緩存功能以提高讀取效率。其中他們的共同接口是Reader。

游戲開發中的角色裝備系統

在游戲開發中,角色裝備(如盔甲、武器)通常使用裝飾器模式。例如,一個基礎角色可以通過不同裝備來增強屬性,如增加攻擊力、防御力等。

Character warrior = new Warrior();
warrior = new ArmorDecorator(warrior);  // 增加防御
warrior = new SwordDecorator(warrior);  // 增加攻擊力

總結

裝飾器模式通過“動態增強”而非“本質改變”的設計理念,為軟件設計提供了高度的靈活性和可擴展性。本文以生活中“換裝打扮”的生動場景為引,巧妙類比了裝飾器模式的核心思想——在不修改對象自身的基礎上,通過層層疊加裝飾器來擴展功能。

核心價值體現:
靈活組合,動態擴展
如同男孩可根據場合自由切換妝容和服飾,裝飾器模式允許在運行時動態添加或替換功能。例如,先穿簡約服裝,再化妝,最后換宴會禮服,每一步裝飾都獨立且可逆,避免繼承帶來的僵化性。

職責分離,結構清晰
通過抽象裝飾器(PeopleDecorator)封裝原始對象,將核心功能(getColor())與裝飾邏輯(美白、換裝)解耦。具體裝飾器僅關注自身新增功能(MakeupDecorator專注美化膚色),代碼可讀性和維護性顯著提升。

遵循開閉原則
新增裝飾器(添加“配飾裝飾器”)無需修改現有代碼,只需繼承抽象裝飾器即可。這種設計支持系統的漸進式擴展,降低耦合度,符合“對擴展開放,對修改關閉”的原則。

實踐啟示:
裝飾器模式尤其適用于需動態、透明地擴展對象功能的場景。例如,Java I/O流中BufferedReader對FileReader的增強,或Web請求處理中的中間件鏈式調用。本文的男孩換裝案例直觀展現了裝飾器的鏈式調用特性——每次裝飾均基于前一步的結果,最終形成功能疊加或覆蓋的效果(最后一次換裝決定最終衣著)。

總之,裝飾器模式如同為對象穿上“功能外衣”,讓代碼在保持簡潔的同時,具備應對復雜需求的優雅擴展能力,是提升系統設計彈性的重要工具。

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

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

相關文章

【Easylive】HikariCP 介紹

【Easylive】項目常見問題解答(自用&持續更新中…) 匯總版 HikariCP 是目前 Java 生態中最快、最輕量級的高性能 JDBC 連接池,被 Spring Boot 2.x 及更高版本選為 默認數據庫連接池。它的名字來源于日語“光”(Hikari&#xf…

清晰易懂的Cursor實現AI編程從安裝到實戰TodoList開發

一、Cursor簡介與安裝部署 什么是Cursor? Cursor是一款基于AI的智能代碼編輯器,它集成了強大的AI編程助手功能,能夠通過自然語言交互幫助開發者生成、優化和調試代碼。與傳統的代碼編輯器不同,Cursor可以理解你的編程意圖&#…

【Django】教程-2-前端-目錄結構介紹

【Django】教程-1-安裝創建項目目錄結構介紹 3. 前端文件配置 3.1 目錄介紹 在app下創建static文件夾, 是根據setting中的配置來的 STATIC_URL ‘static/’ templates目錄,編寫HTML模板(含有模板語法,繼承,{% static ‘xx’ …

注意!ChatGPT 全新 AI 圖像功能延遲對免費用戶開放

2025 年 3 月 25 日,OpenAI 正式宣布在 ChatGPT 中推出基于 GPT-4o 模型的全新原生圖像生成功能。 這一功能允許用戶通過對話生成和編輯圖像,支持從寫實風格到插圖風格的多種形式。OpenAI 首席執行官薩姆?奧特曼(Sam Altman)在社…

優化webpack打包體積思路

Webpack 打包過大的問題通常會導致頁面加載變慢,影響用戶體驗。可以從代碼優化、依賴優化、構建優化等多個角度入手來減少打包體積: 代碼優化 (1)按需加載(代碼拆分) ① 路由懶加載 如果你的項目使用 Vu…

HarmonyOS Next~鴻蒙元服務開發指南:核心功能與實踐

HarmonyOS Next~鴻蒙元服務開發指南:核心功能與實踐 一、元服務核心概念 原子化服務定義 元服務(原子服務)是鴻蒙系統的核心架構單元,具備獨立業務能力的輕量化服務模塊,支持免安裝、跨設備調用和智能分發…

git錯誤:fatal: detected dubious ownership in repository at xxxxxx

1、報錯說明 這個錯誤通常是由于Git倉庫目錄的擁有者或權限問題引起的。Git檢測到倉庫目錄的所有權可能存在不一致或不安全的情況。 通常導致此報錯的可能原因: (1)文件或目錄的擁有者不一致: 倉庫目錄中的某些文件或子目錄可能…

【計算機網絡】OSI七層模型完全指南:從比特流到應用交互的逐層拆解

OSI模型 導讀一、概念二、模型層次結構2.1 物理層(Physical Layer)2.2 數據鏈路層(Data Link Layer)?2.3 ?網絡層(Network Layer)?2.4 ?傳輸層(Transport Layer)?2.5 ?會話層&…

零基礎被迫參加CTF比賽?CTF高頻解題技巧與經驗分享

CTF(Capture The Flag)比賽中的高頻解題技巧通常涵蓋了以下幾類技術,涉及從逆向工程、二進制漏洞利用到Web安全、密碼學等多個領域。以下是一些高頻解題技巧: 1. 逆向工程(Reverse Engineering) 靜態分析&a…

markdown 文件轉 word

將 Markdown 文件轉換為 Word 文檔,可以使用多種方法。以下是幾種常見的方法: 方法1:使用在線轉換工具 有許多在線服務可以將 Markdown 文件轉換為 Word 文檔。例如: Pandoc - 一個非常流行的命令行工具,也可以用來轉…

【第十三屆“泰迪杯”數據挖掘挑戰賽】【2025泰迪杯】【思路篇】A題解題全流程(持續更新)

【第十三屆“泰迪杯”數據挖掘挑戰賽】【2025泰迪杯】A題解題全流程-思路(持續更新) 寫在前面: 1、A題、C題將會持續更新,陸續更新發布文章 2、賽題交流咨詢Q群:1037590285 3、全家桶依舊包含: 代碼、…

T11 TensorFlow入門實戰——優化器對比實驗

🍨 本文為🔗365天深度學習訓練營 中的學習紀錄博客🍖 原作者:K同學啊 | 接輔導、項目定制 一、前期準備 1. 導入數據 # Import the required libraries import pathlib import matplotlib.pyplot as plt import tensorflow as t…

Docker部署sprintboot后端項目

創建Docker網絡 docker network create icjs 部署Redis docker run -d \--network icjs \--name redis \-p 6379:6379 \redis:latest數據持久化 docker run --restartalways --network icjs -p 6379:6379 --name redis -v /opt/docker/redis/redis.conf:/etc/redis/redis.c…

01小游戲

問題描述 小明得到了一個長度為 nn 的字符串 ss ,該字符串都是由數字 00 和 11 組成,并且下標從 11 開始,小明現在需要對這個字符串進行 qq 次操作,每次操作包含以下兩種操作之一: 操作 11 :小明查詢該字符…

Androidstudio開發,實現商品分類

文章目錄 1. 功能需求2. 代碼實現過程1. 編寫布局文件2. 創建商品分類(Adapter)適配器3. 實現商品分類Activity4. 在res/values/ 下新建 array.xml ,用于添加商品分類數據5. 效果演示 6. 關于作者其它項目視頻教程介紹 1. 功能需求 顯示商品分…

Linux快速安裝docker和docker-componse步驟

在 CentOS 7 上安裝 Docker 和 Docker Compose 的步驟如下: 1. 安裝 Docker 1.1. 更新系統 首先,確保你的系統是最新版本: sudo yum update -y1.2. 安裝必要的包 安裝 yum-utils,這是管理 YUM 源的工具: sudo yu…

VBA代碼解決方案第二十三講 EXCEL中,如何刪除工作表中的空白行

《VBA代碼解決方案》(版權10028096)這套教程是我最早推出的教程,目前已經是第三版修訂了。這套教程定位于入門后的提高,在學習這套教程過程中,側重點是要理解及掌握我的“積木編程”思想。要靈活運用教程中的實例像搭積木一樣把自己喜歡的代碼…

Pytorch--tensor.view()

在 PyTorch 中,tensor.view() 是一個常用的方法,用于改變張量(Tensor)的形狀(shape),但不會改變其數據本身。它類似于 NumPy 的 reshape(),但有一些關鍵區別。 1. 基本用法 import …

【機器學習】——機器學習思考總結

摘要 這篇文章深入探討了機器學習中的數據相關問題,重點分析了神經網絡(DNN)的學習機制,包括層級特征提取、非線性激活函數、反向傳播和梯度下降等關鍵機制。同時,文章還討論了數據集大小的標準、機器學習訓練數據量的…

CoAP Shell 筆記

CoAP Shell 筆記 1. 概述 CoAP (Constrained Application Protocol) 是一種專為物聯網 (IoT) 中資源受限的節點和網絡設計的 RESTful Web 傳輸協議。CoAP Shell 是一個基于命令行的交互式工具,用于與支持 CoAP 的服務器進行交互。 2. 主要功能 協議支持&#xff…