Java?裝飾器模式Decorator詳解及實現(xiàn)步驟
在 Java 的世界里,設(shè)計模式是開發(fā)者手中的利器,它們幫助我們以更優(yōu)雅、更靈活的方式構(gòu)建軟件系統(tǒng)。今天,我們就來深入探討其中一種非常實用的設(shè)計模式 —— 裝飾器模式(Decorator Pattern)。?
一、裝飾器模式概述?
裝飾器模式屬于結(jié)構(gòu)型設(shè)計模式,它允許向一個現(xiàn)有的對象添加新的功能,同時又不改變其結(jié)構(gòu)。這就好比給一個普通的杯子加上杯蓋、杯套,讓它具備保溫、防燙等功能,而杯子本身的基本結(jié)構(gòu)并沒有發(fā)生變化。在軟件開發(fā)中,當我們需要在運行時動態(tài)地為對象添加職責,并且避免通過繼承來擴展功能帶來的類層次結(jié)構(gòu)復(fù)雜問題時,裝飾器模式就派上用場了。?
裝飾器模式主要包含以下幾個角色:?
- 抽象組件(Component):定義一個抽象接口,規(guī)范具體組件和裝飾器的行為。?
- 具體組件(Concrete Component):實現(xiàn)抽象組件接口,是被裝飾的具體對象。?
- 抽象裝飾器(Decorator):繼承或?qū)崿F(xiàn)抽象組件接口,持有一個抽象組件的引用,并定義一個可以動態(tài)添加職責的方法。?
- 具體裝飾器(Concrete Decorator):實現(xiàn)抽象裝飾器接口,負責為具體組件添加具體的功能。

二、裝飾器模式的實現(xiàn)步驟
1.故事背景:機器人功能擴展的兩種方案
在智能家居領(lǐng)域,某科技公司推出了第一代家用機器人,它具備三個核心功能:對話、唱歌和播放音樂。

// 第一代機器人:基礎(chǔ)功能
interface Robot {
void talk(); // 對話
void sing(); // 唱歌
void playMusic(); // 播放音樂
}
class FirstGenerationRobot implements Robot {
@Override
public void talk() {
System.out.println("機器人:你好,我能陪你聊天");
}
@Override
public void sing() {
System.out.println("機器人:正在播放《青花瓷》");
}
@Override
public void playMusic() {
System.out.println("機器人:正在播放輕音樂");
}
}隨著用戶需求升級,廠家希望擴展機器人的功能,讓它能夠掃地和跳舞。針對這個需求,有兩種技術(shù)方案可供選擇:

⑴.方案一:傳統(tǒng)繼承(廠家升級方案)
廠家選擇開發(fā)第二代機器人,通過繼承第一代產(chǎn)品并添加新功能:
?? 接口定義
// 基礎(chǔ)接口:第一代機器人支持的功能
interface Robot {
void talk();
void sing();
void playMusic();
}?? 類實現(xiàn)
// 第一代機器人(基礎(chǔ)實現(xiàn))
class FirstGenerationRobot implements Robot {
@Override
public void talk() {
System.out.println("對話中...");
}
@Override
public void sing() {
System.out.println("正在唱歌...");
}
@Override
public void playMusic() {
System.out.println("播放音樂中...");
}
}
// 第二代機器人:通過繼承方式擴展功能
class SecondGenerationRobot extends FirstGenerationRobot {
public void sweep() {
System.out.println("正在掃地...");
}
public void dance() {
System.out.println("正在跳舞...");
}
}?? 測試代碼
public class InheritanceTest {
public static void main(String[] args) {
System.out.println("=== 繼承方式測試 ===");
SecondGenerationRobot robot = new SecondGenerationRobot();
robot.talk();
robot.sing();
robot.playMusic();
robot.sweep(); // 擴展功能
robot.dance(); // 擴展功能
}
}⑵.方案二:裝飾器模式

通過組合方式動態(tài)添加新功能:
以下是根據(jù)機器人例子實現(xiàn)的裝飾器模式代碼及詳細解釋:
抽象組件(Robot 接口)
interface Robot {
void talk(); // 對話
void sing(); // 唱歌
void playMusic(); // 放音樂
}- 作用:定義機器人的基本功能,作為裝飾器模式的核心接口,規(guī)范所有機器人(包括原始機器人和裝飾后的機器人)的行為。
具體組件(第一代機器人)
class FirstGenerationRobot implements Robot {
@Override
public void talk() {
System.out.println("第一代機器人:對話");
}
@Override
public void sing() {
System.out.println("第一代機器人:唱歌");
}
@Override
public void playMusic() {
System.out.println("第一代機器人:放音樂");
}
}- 作用:實現(xiàn)抽象組件,是被裝飾的原始對象(第一代機器人,具有基本功能)。
抽象裝飾器(RobotDecorator)
abstract class RobotDecorator implements Robot {
protected Robot robot; // 持有被裝飾的機器人對象
public RobotDecorator(Robot robot) {
this.robot = robot;
}
// 轉(zhuǎn)發(fā)原始功能(保持原有功能不變)
@Override
public void talk() {
robot.talk();
}
@Override
public void sing() {
robot.sing();
}
@Override
public void playMusic() {
robot.playMusic();
}
}- 作用:作為裝飾器的基類,繼承抽象組件接口,通過組合(關(guān)聯(lián))持有原始機器人對象。它實現(xiàn)了原始功能的轉(zhuǎn)發(fā),確保裝飾時不破壞原有功能,同時為具體裝飾器提供統(tǒng)一的擴展框架。
具體裝飾器(添加拖地和跳舞功能)
// 拖地裝飾器:繼承自RobotDecorator,用于為機器人添加拖地功能
class SweepFloorDecorator extends RobotDecorator {
// 構(gòu)造函數(shù):接收被裝飾的機器人實例
public SweepFloorDecorator(Robot robot) {
// 通過super調(diào)用父類構(gòu)造函數(shù),保存對原始機器人的引用
super(robot);
}
public void sweepFloor() { // 新增功能:拖地
System.out.println("裝飾后:拖地");
}
}
// 跳舞裝飾器
class DanceDecorator extends RobotDecorator {
public DanceDecorator(Robot robot) {
super(robot);
}
public void dance() { // 新增功能:跳舞
System.out.println("裝飾后:跳舞");
}
}測試代碼
public class RobotDemo {
public static void main(String[] args) {
// 原始機器人(第一代)
Robot robot = new FirstGenerationRobot();
robot.talk(); // 原始功能:對話
robot.sing(); // 原始功能:唱歌
robot.playMusic(); // 原始功能:放音樂
// 裝飾器擴展:添加拖地功能
SweepFloorDecorator decoratedWithSweep = new SweepFloorDecorator(robot);
decoratedWithSweep.talk(); // 保留原始功能
decoratedWithSweep.sweepFloor(); // 新增功能:拖地
// 再裝飾:添加跳舞功能
DanceDecorator fullyDecorated = new DanceDecorator(decoratedWithSweep);
fullyDecorated.talk(); // 保留原始功能
// 正確調(diào)用拖地功能
decoratedWithSweep.sweepFloor(); // 拖地功能
// 新增功能:跳舞
fullyDecorated.dance();
}
}
裝飾器模式通過組合而非繼承,實現(xiàn)了運行時動態(tài)擴展對象功能,避免了繼承帶來的類爆炸問題,是處理 “對象功能擴展” 的優(yōu)雅方案。在機器人例子中,利用裝飾器模式,無需等待廠家更新(繼承方式),即可快速為第一代機器人添加拖地、跳舞功能,體現(xiàn)了模式的靈活性和實用性。

- 繼承機制適合功能較為穩(wěn)定、擴展需求明確的場景,實現(xiàn)簡單,但不夠靈活。
- 裝飾器模式適合需要動態(tài)組合功能、避免類爆炸的情況,雖然實現(xiàn)略復(fù)雜,但更符合開閉原則(對擴展開放,對修改關(guān)閉)。
三、流程圖和內(nèi)存圖


1.創(chuàng)建基礎(chǔ)機器人
Robot robot = new FirstGenerationRobot();
- 創(chuàng)建第一代機器人實例,具備基礎(chǔ)功能(talk/sing/playMusic)
2.第一次裝飾:添加拖地功能
SweepFloorDecorator decoratedWithSweep = new SweepFloorDecorator(robot);
SweepFloorDecorator持有對原始機器人的引用- 繼承了
RobotDecorator的默認實現(xiàn)(轉(zhuǎn)發(fā)所有方法調(diào)用)
3.調(diào)用原始功能
decoratedWithSweep.talk();
- 執(zhí)行流程:
decoratedWithSweep.talk()調(diào)用RobotDecorator的實現(xiàn)RobotDecorator轉(zhuǎn)發(fā)給被裝飾對象:robot.talk()- 最終執(zhí)行
FirstGenerationRobot.talk()
4.調(diào)用新增功能
decoratedWithSweep.sweepFloor();
- 直接調(diào)用
SweepFloorDecorator新增的方法 - 輸出:"裝飾后:拖地"
5.第二次裝飾:添加跳舞功能
DanceDecorator fullyDecorated = new DanceDecorator(decoratedWithSweep);
DanceDecorator持有對SweepFloorDecorator的引用- 形成裝飾器嵌套結(jié)構(gòu):
DanceDecorator -> SweepFloorDecorator -> FirstGenerationRobot
6.調(diào)用原始功能(多層裝飾后)
fullyDecorated.talk();
- 執(zhí)行流程:
fullyDecorated.talk()調(diào)用RobotDecorator的實現(xiàn)- 轉(zhuǎn)發(fā)給被裝飾對象:
decoratedWithSweep.talk() decoratedWithSweep.talk()再次轉(zhuǎn)發(fā):robot.talk()- 最終執(zhí)行
FirstGenerationRobot.talk()
7.調(diào)用第一層裝飾器功能
decoratedWithSweep.sweepFloor();
- 必須通過
decoratedWithSweep引用調(diào)用 - 因為
fullyDecorated類型是DanceDecorator,沒有直接暴露sweepFloor()方法
8.調(diào)用第二層裝飾器功能
fullyDecorated.dance();
- 直接調(diào)用
DanceDecorator新增的方法 - 輸出:"裝飾后:跳舞"
3 個
Robot引用的指向?qū)ο?/p>
變量
robot
- 類型:
Robot- 指向:
FirstGenerationRobot實例(原始機器人)
SweepFloorDecorator內(nèi)部的robot成員變量
- 類型:
Robot(父類RobotDecorator的protected Robot robot)- 指向:
FirstGenerationRobot實例(與變量robot指向同一個對象)
DanceDecorator內(nèi)部的robot成員變量
- 類型:
Robot(父類RobotDecorator的protected Robot robot)- 指向:
SweepFloorDecorator實例(與前兩個引用指向不同對象)
引用的內(nèi)存地址比較
Robot robot = new FirstGenerationRobot(); SweepFloorDecorator decoratedWithSweep = new SweepFloorDecorator(robot); DanceDecorator fullyDecorated = new DanceDecorator(decoratedWithSweep); // 內(nèi)存地址比較(假設(shè)對象內(nèi)存地址為示例值) robot: 0x1000 // 指向 FirstGenerationRobot decoratedWithSweep.robot: 0x1000 // 指向 FirstGenerationRobot(與 robot 相同) fullyDecorated.robot: 0x2000 // 指向 SweepFloorDecorator(與前兩者不同)
robot和decoratedWithSweep.robot指向相同對象(內(nèi)存地址均為0x1000)。fullyDecorated.robot指向不同對象(內(nèi)存地址0x2000,即SweepFloorDecorator實例)。
四、實戰(zhàn)中的裝飾器模式
1. Java I/O 庫中的應(yīng)用
// 輸入流裝飾示例:
InputStream fileInput = new FileInputStream("data.txt");
InputStream bufferInput = new BufferedInputStream(fileInput);
DataInputStream dataInput = new DataInputStream(bufferInput);
// 功能動態(tài)組合:
// 基礎(chǔ)功能:FileInputStream
// 裝飾1:添加緩沖功能 BufferedInputStream
// 裝飾2:添加數(shù)據(jù)處理功能 DataInputStream2. Spring 框架中的應(yīng)用
// Spring Security的認證過濾器鏈:
FilterChain filterChain = new UsernamePasswordAuthenticationFilter(
new BasicAuthenticationFilter(
new SecurityContextPersistenceFilter()
)
);
// 每個過濾器都是一個裝飾器,動態(tài)增強請求處理能力到此這篇關(guān)于Java 裝飾器模式Decorator詳解及實現(xiàn)步驟的文章就介紹到這了,更多相關(guān)Java 裝飾器模式Decorator內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot的控制反轉(zhuǎn)和自動裝配示例代碼
這篇文章主要介紹了springboot的控制反轉(zhuǎn)和自動裝配的相關(guān)知識,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06
如何開發(fā)一個簡單的Akka Java應(yīng)用
這篇文章主要介紹了如何開發(fā)一個簡單的Akka Java應(yīng)用 ,幫助大家使用Java創(chuàng)建Akka項目并將其打包,感興趣的朋友可以了解下2020-10-10
JAVA簡單工廠模式(從現(xiàn)實生活角度理解代碼原理)
本文主要介紹了JAVA簡單工廠模式(從現(xiàn)實生活角度理解代碼原理)的相關(guān)知識。具有很好的參考價值。下面跟著小編一起來看下吧2017-03-03
Python如何使用@property @x.setter及@x.deleter
這篇文章主要介紹了Python如何使用@property @x.setter及@x.deleter,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-05-05

