欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?裝飾器模式Decorator詳解及實(shí)現(xiàn)步驟

 更新時(shí)間:2025年07月17日 11:01:56   作者:magic?245  
裝飾器模式通過組合動(dòng)態(tài)擴(kuò)展對象功能,避免繼承導(dǎo)致的類爆炸,適用于運(yùn)行時(shí)靈活添加職責(zé)的場景,廣泛應(yīng)用于Java I/O和Spring框架,提升代碼可維護(hù)性與擴(kuò)展性,本文介紹Java裝飾器模式Decorator詳解及實(shí)現(xiàn)步驟,感興趣的朋友一起看看吧

在 Java 的世界里,設(shè)計(jì)模式是開發(fā)者手中的利器,它們幫助我們以更優(yōu)雅、更靈活的方式構(gòu)建軟件系統(tǒng)。今天,我們就來深入探討其中一種非常實(shí)用的設(shè)計(jì)模式 —— 裝飾器模式(Decorator Pattern)。?

一、裝飾器模式概述?

裝飾器模式屬于結(jié)構(gòu)型設(shè)計(jì)模式,它允許向一個(gè)現(xiàn)有的對象添加新的功能,同時(shí)又不改變其結(jié)構(gòu)。這就好比給一個(gè)普通的杯子加上杯蓋、杯套,讓它具備保溫、防燙等功能,而杯子本身的基本結(jié)構(gòu)并沒有發(fā)生變化。在軟件開發(fā)中,當(dāng)我們需要在運(yùn)行時(shí)動(dòng)態(tài)地為對象添加職責(zé),并且避免通過繼承來擴(kuò)展功能帶來的類層次結(jié)構(gòu)復(fù)雜問題時(shí),裝飾器模式就派上用場了。?

裝飾器模式主要包含以下幾個(gè)角色:?

  1. 抽象組件(Component):定義一個(gè)抽象接口,規(guī)范具體組件和裝飾器的行為。?
  2. 具體組件(Concrete Component):實(shí)現(xiàn)抽象組件接口,是被裝飾的具體對象。?
  3. 抽象裝飾器(Decorator):繼承或?qū)崿F(xiàn)抽象組件接口,持有一個(gè)抽象組件的引用,并定義一個(gè)可以動(dòng)態(tài)添加職責(zé)的方法。?
  4. 具體裝飾器(Concrete Decorator):實(shí)現(xiàn)抽象裝飾器接口,負(fù)責(zé)為具體組件添加具體的功能。

二、裝飾器模式的實(shí)現(xiàn)步驟

1.故事背景:機(jī)器人功能擴(kuò)展的兩種方案

在智能家居領(lǐng)域,某科技公司推出了第一代家用機(jī)器人,它具備三個(gè)核心功能:對話、唱歌和播放音樂。

// 第一代機(jī)器人:基礎(chǔ)功能
interface Robot {
    void talk();    // 對話
    void sing();    // 唱歌
    void playMusic(); // 播放音樂
}
class FirstGenerationRobot implements Robot {
    @Override
    public void talk() {
        System.out.println("機(jī)器人:你好,我能陪你聊天");
    }
    @Override
    public void sing() {
        System.out.println("機(jī)器人:正在播放《青花瓷》");
    }
    @Override
    public void playMusic() {
        System.out.println("機(jī)器人:正在播放輕音樂");
    }
}

隨著用戶需求升級,廠家希望擴(kuò)展機(jī)器人的功能,讓它能夠掃地和跳舞。針對這個(gè)需求,有兩種技術(shù)方案可供選擇:

⑴.方案一:傳統(tǒng)繼承(廠家升級方案)

廠家選擇開發(fā)第二代機(jī)器人,通過繼承第一代產(chǎn)品并添加新功能:

?? 接口定義

// 基礎(chǔ)接口:第一代機(jī)器人支持的功能
interface Robot {
    void talk();
    void sing();
    void playMusic();
}

?? 類實(shí)現(xiàn)

// 第一代機(jī)器人(基礎(chǔ)實(shí)現(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("播放音樂中...");
    }
}
// 第二代機(jī)器人:通過繼承方式擴(kuò)展功能
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();  // 擴(kuò)展功能
        robot.dance();   // 擴(kuò)展功能
    }
}

⑵.方案二:裝飾器模式

通過組合方式動(dòng)態(tài)添加新功能:

以下是根據(jù)機(jī)器人例子實(shí)現(xiàn)的裝飾器模式代碼及詳細(xì)解釋:

抽象組件(Robot 接口)

interface Robot {
    void talk();   // 對話
    void sing();   // 唱歌
    void playMusic(); // 放音樂
}
  • 作用:定義機(jī)器人的基本功能,作為裝飾器模式的核心接口,規(guī)范所有機(jī)器人(包括原始機(jī)器人和裝飾后的機(jī)器人)的行為。

具體組件(第一代機(jī)器人)

class FirstGenerationRobot implements Robot {
    @Override
    public void talk() {
        System.out.println("第一代機(jī)器人:對話");
    }
    @Override
    public void sing() {
        System.out.println("第一代機(jī)器人:唱歌");
    }
    @Override
    public void playMusic() {
        System.out.println("第一代機(jī)器人:放音樂");
    }
}
  • 作用:實(shí)現(xiàn)抽象組件,是被裝飾的原始對象(第一代機(jī)器人,具有基本功能)。

抽象裝飾器(RobotDecorator)

abstract class RobotDecorator implements Robot {
    protected Robot robot; // 持有被裝飾的機(jī)器人對象
    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))持有原始機(jī)器人對象。它實(shí)現(xiàn)了原始功能的轉(zhuǎn)發(fā),確保裝飾時(shí)不破壞原有功能,同時(shí)為具體裝飾器提供統(tǒng)一的擴(kuò)展框架。

具體裝飾器(添加拖地和跳舞功能)

Java 中的 super 關(guān)鍵字

// 拖地裝飾器:繼承自RobotDecorator,用于為機(jī)器人添加拖地功能
class SweepFloorDecorator extends RobotDecorator {
    // 構(gòu)造函數(shù):接收被裝飾的機(jī)器人實(shí)例
    public SweepFloorDecorator(Robot robot) {
        // 通過super調(diào)用父類構(gòu)造函數(shù),保存對原始機(jī)器人的引用
        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) {
        // 原始機(jī)器人(第一代)
        Robot robot = new FirstGenerationRobot();
        robot.talk();   // 原始功能:對話
        robot.sing();   // 原始功能:唱歌
        robot.playMusic(); // 原始功能:放音樂
        // 裝飾器擴(kuò)展:添加拖地功能
        SweepFloorDecorator decoratedWithSweep = new SweepFloorDecorator(robot);
        decoratedWithSweep.talk(); // 保留原始功能
        decoratedWithSweep.sweepFloor(); // 新增功能:拖地
        // 再裝飾:添加跳舞功能
        DanceDecorator fullyDecorated = new DanceDecorator(decoratedWithSweep);
        fullyDecorated.talk(); // 保留原始功能
        // 正確調(diào)用拖地功能
        decoratedWithSweep.sweepFloor(); // 拖地功能
        // 新增功能:跳舞
        fullyDecorated.dance();
    }
}

裝飾器模式通過組合而非繼承,實(shí)現(xiàn)了運(yùn)行時(shí)動(dòng)態(tài)擴(kuò)展對象功能,避免了繼承帶來的類爆炸問題,是處理 “對象功能擴(kuò)展” 的優(yōu)雅方案。在機(jī)器人例子中,利用裝飾器模式,無需等待廠家更新(繼承方式),即可快速為第一代機(jī)器人添加拖地、跳舞功能,體現(xiàn)了模式的靈活性和實(shí)用性。

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

三、流程圖和內(nèi)存圖

1.創(chuàng)建基礎(chǔ)機(jī)器人

Robot robot = new FirstGenerationRobot();
  • 創(chuàng)建第一代機(jī)器人實(shí)例,具備基礎(chǔ)功能(talk/sing/playMusic)

2.第一次裝飾:添加拖地功能

SweepFloorDecorator decoratedWithSweep = new SweepFloorDecorator(robot);
  • SweepFloorDecorator 持有對原始機(jī)器人的引用
  • 繼承了 RobotDecorator 的默認(rèn)實(shí)現(xiàn)(轉(zhuǎn)發(fā)所有方法調(diào)用)

3.調(diào)用原始功能

decoratedWithSweep.talk();
  • 執(zhí)行流程:
    • decoratedWithSweep.talk() 調(diào)用 RobotDecorator 的實(shí)現(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 的實(shí)現(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)用
  • 因?yàn)?nbsp;fullyDecorated 類型是 DanceDecorator,沒有直接暴露 sweepFloor() 方法

8.調(diào)用第二層裝飾器功能

fullyDecorated.dance();
  • 直接調(diào)用 DanceDecorator 新增的方法
  • 輸出:"裝飾后:跳舞"

3 個(gè) Robot 引用的指向?qū)ο?/p>

  1. 變量 robot

    • 類型:Robot
    • 指向:FirstGenerationRobot 實(shí)例(原始機(jī)器人)
  2. SweepFloorDecorator 內(nèi)部的 robot 成員變量

    • 類型:Robot(父類 RobotDecorator 的 protected Robot robot
    • 指向:FirstGenerationRobot 實(shí)例(與變量 robot 指向同一個(gè)對象)
  3. DanceDecorator 內(nèi)部的 robot 成員變量

    • 類型:Robot(父類 RobotDecorator 的 protected Robot robot
    • 指向:SweepFloorDecorator 實(shí)例(與前兩個(gè)引用指向不同對象)

引用的內(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 實(shí)例)。

四、實(shí)戰(zhàn)中的裝飾器模式

1. Java I/O 庫中的應(yīng)用

// 輸入流裝飾示例:
InputStream fileInput = new FileInputStream("data.txt");
InputStream bufferInput = new BufferedInputStream(fileInput);
DataInputStream dataInput = new DataInputStream(bufferInput);
// 功能動(dòng)態(tài)組合:
// 基礎(chǔ)功能:FileInputStream
// 裝飾1:添加緩沖功能 BufferedInputStream
// 裝飾2:添加數(shù)據(jù)處理功能 DataInputStream

2. Spring 框架中的應(yīng)用

// Spring Security的認(rèn)證過濾器鏈:
FilterChain filterChain = new UsernamePasswordAuthenticationFilter(
                            new BasicAuthenticationFilter(
                                new SecurityContextPersistenceFilter()
                            )
                        );
// 每個(gè)過濾器都是一個(gè)裝飾器,動(dòng)態(tài)增強(qiáng)請求處理能力

到此這篇關(guān)于Java 裝飾器模式Decorator詳解及實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)Java 裝飾器模式Decorator內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis動(dòng)態(tài)SQL?foreach批量操作方法

    Mybatis動(dòng)態(tài)SQL?foreach批量操作方法

    這篇文章主要介紹了Mybatis動(dòng)態(tài)SQL?foreach批量操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • 詳解SpringBoot定時(shí)任務(wù)說明

    詳解SpringBoot定時(shí)任務(wù)說明

    本篇文章主要介紹了詳解SpringBoot定時(shí)任務(wù)說明,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • Java實(shí)現(xiàn)JDBC向數(shù)據(jù)庫批量插入

    Java實(shí)現(xiàn)JDBC向數(shù)據(jù)庫批量插入

    在Java項(xiàng)目中可能會(huì)出現(xiàn)大量向數(shù)據(jù)庫中插入的情況,本文主要介紹了Java實(shí)現(xiàn)JDBC向數(shù)據(jù)庫批量插入,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • intellij idea創(chuàng)建第一個(gè)動(dòng)態(tài)web項(xiàng)目的步驟方法

    intellij idea創(chuàng)建第一個(gè)動(dòng)態(tài)web項(xiàng)目的步驟方法

    這篇文章主要介紹了intellij idea創(chuàng)建第一個(gè)動(dòng)態(tài)web項(xiàng)目的步驟方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 多線程計(jì)數(shù),怎么保持計(jì)數(shù)準(zhǔn)確的方法

    多線程計(jì)數(shù),怎么保持計(jì)數(shù)準(zhǔn)確的方法

    這篇文章主要介紹了多線程計(jì)數(shù)的方法,有需要的朋友可以參考一下
    2014-01-01
  • 國內(nèi)分布式框架Dubbo使用詳解

    國內(nèi)分布式框架Dubbo使用詳解

    這篇文章主要為大家介紹了國內(nèi)分布式框架Dubbo使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • JDBC如何通過SSL方式連接MySQL

    JDBC如何通過SSL方式連接MySQL

    文章介紹了如何配置MySQL以支持SSL連接,并通過JDBC進(jìn)行安全連接,主要內(nèi)容包括查看MySQL SSL支持、創(chuàng)建SSL連接用戶、配置用戶是否強(qiáng)制使用SSL、JDBC配置導(dǎo)入證書以及使用Go編寫一個(gè)簡單的HTTP文件服務(wù)器來提供SSL證書
    2025-02-02
  • SpringBoot用多線程批量導(dǎo)入數(shù)據(jù)庫實(shí)現(xiàn)方法

    SpringBoot用多線程批量導(dǎo)入數(shù)據(jù)庫實(shí)現(xiàn)方法

    這篇文章主要介紹了SpringBoot用多線程批量導(dǎo)入數(shù)據(jù)庫實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • Java在web頁面上的編碼解碼處理及中文URL亂碼解決

    Java在web頁面上的編碼解碼處理及中文URL亂碼解決

    這篇文章主要介紹了Java在web頁面上的編碼解碼處理及中文URL亂碼解決,文中所介紹的兩種使用過濾器解決中文鏈接亂碼的方法非常有效,需要的朋友可以參考下
    2016-02-02
  • 詳解通過JDBC進(jìn)行簡單的增刪改查(以MySQL為例)

    詳解通過JDBC進(jìn)行簡單的增刪改查(以MySQL為例)

    JDBC是用于執(zhí)行SQL語句的一類Java API,通過JDBC使得我們可以直接使用Java編程來對關(guān)系數(shù)據(jù)庫進(jìn)行操作。通過封裝,可以使開發(fā)人員使用純Java API完成SQL的執(zhí)行。
    2017-01-01

最新評論