設計模式 | 裝飾模式(decorator)

来源:https://www.cnblogs.com/imoqian/archive/2019/01/28/10330427.html
-Advertisement-
Play Games

定義: 裝飾模式是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。 結構:(書中圖,侵刪) 一個被裝飾介面類:從具體類中抽象出來,擁有用於修飾的一個公共方法 若幹被裝飾具體類;繼承於被裝飾介面類 一個抽象裝飾類:繼承於被裝飾介面類 ...


定義:

裝飾模式是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。

結構:(書中圖,侵刪)

一個被裝飾介面類:從具體類中抽象出來,擁有用於修飾的一個公共方法 若幹被裝飾具體類;繼承於被裝飾介面類 一個抽象裝飾類:繼承於被裝飾介面類 若幹具體裝飾類:具體的裝飾方法   裝飾模式是為了擴展原有方法(即已經存在的方法)的功能 ,所以是為了給方法添加功能,而不是給類新增方法。(我一開始就這麼誤解了,導致整個看下來感覺怪怪的,後面才後知後覺的反應過來)。 直接在原類中增加違反了開放-封閉原則;使用繼承都寫在子類中沒有那麼靈活,且不好復用。

例子:

模擬寵物去做造型 美容院提供:洗澡、染色、修剪、穿衣服等服務。   被裝飾介面類:寵物類
package designpattern.decorator;

public abstract class Pet {
    String name;

    Pet() {// 因為子類要使用其他參數的構造函數,需要調用父類的預設(無參)構造方法
    }

    Pet(String name) {
        this.name = name;
    }

    Pet(String name, int test) {
        this.name = name;
    }

    public abstract void beautify();
}

若幹被裝飾具體類:貓、狗

package designpattern.decorator;

public class Cat extends Pet {
    public Cat(String name) {
        this.name = name;
    }

    @Override
    public void beautify() {
        System.out.println(name + ":貓正在打扮~");
    }

}
package designpattern.decorator;

public class Dog extends Pet {
    public Dog(String name) {
        this.name = name;
    }

    @Override
    public void beautify() {
        System.out.println(name + ":狗正在打扮~");
    }

}

抽象裝飾類:美容類

package designpattern.decorator;

public class Beautify extends Pet {
    Pet pet;

    Beautify(Pet pet) {
        this.pet = pet;
    }

    @Override
    public void beautify() {
        System.out.println("裝飾父類beautify()");
        pet.beautify();
    }

}
若幹具體裝飾類:洗澡、染色、修剪、穿衣服
package designpattern.decorator;

public class Shower extends Beautify{

    Shower(Pet pet) {
        super(pet);
    }

    @Override
    public void beautify() {
        super.beautify();
        System.out.println("洗澡");
    }

}
package designpattern.decorator;

public class Dye extends Beautify {

    Dye(Pet pet) {
        super(pet);
    }

    @Override
    public void beautify() {
        super.beautify();
        System.out.println("染色");
    }
}
package designpattern.decorator;

public class Trim extends Beautify {

    Trim(Pet pet) {
        super(pet);
    }

    @Override
    public void beautify() {
        super.beautify();
        System.out.println("修剪");
    }
}
package designpattern.decorator;

public class Dress extends Beautify {

    Dress(Pet pet) {
        super(pet);
    }

    @Override
    public void beautify() {
        super.beautify();
        System.out.println("穿衣服");
    }
}

客戶端調用:

package designpattern.decorator;

public class Client {
    public static void main(String[] args) {
        Cat cat = new Cat("小喵");
        // 直接調用
        cat.beautify();
        System.out.println("----------------");
        // 裝飾後調用
        Shower showerCat = new Shower(cat);
        Dye dyeCat = new Dye(showerCat);
        Trim trimCat = new Trim(dyeCat);
        trimCat.beautify();
System.
out.println("==================");
Dog dog
= new Dog("小汪"); // 直接調用 dog.beautify(); System.out.println("----------------"); // 裝飾後調用 Shower showerDog = new Shower(dog); Dress dressDog = new Dress(showerDog); dressDog.beautify(); } }

結果:

小喵:貓正在打扮~
----------------
裝飾父類beautify()
裝飾父類beautify()
裝飾父類beautify()
小喵:貓正在打扮~
洗澡
染色
修剪
==================
小汪:狗正在打扮~
----------------
裝飾父類beautify()
裝飾父類beautify()
小汪:狗正在打扮~
洗澡
穿衣服
從輸出能看出,有幾層裝飾,就會調用幾次裝飾父類的beautify()方法。 以上例的狗小汪為例:
通過最底層的穿衣服Dress的方法: 進入方法中 通過super.beautify()方法,調用父類的方法: 再通過多態調用具體的父類,此處為洗澡Shower的方法,重覆上述步驟直至最頂層狗Dog類的beautify()方法: 再回來執行方法中的其餘語句,有一點類似於遞歸的感覺。

總結:

裝飾模式雖然能靈活復用,且能夠規定各個裝飾辦法的執行順序。 但是一旦裝飾類變多後,客戶端的調用會變得相當繁瑣。            
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 適配器模式的定義:將一個類的介面變換成客戶端所期待的另一種介面,從而使原本因介面不匹配而無法在一起工作的兩個類能夠一起工作。 圖解: A、B兩個圖框代表已經塑模成型的物體A和物體B,現在要求把A和B安裝在一起使用,如何安裝?兩者的介面不一致,是不可能安裝在一起使用的,那怎麼辦?引入一個物體C,如下: ...
  • 初學laravel常常看到諸如依賴註入、控制反轉等名詞一臉懵逼,望而生畏,用了一段時間後才明白這些基本的原理,原理其實並不難,關鍵在於怎麼理解。 ...
  • 單一職責原則(Single Responsibility Principle),簡稱SRP。 定義:一個類只負責一件事情; 說明:類的單一職責原則受多重因素制約,實際實現起來,需要考慮項目工期、成本、人員技術水平等 使用:介面一定要做到單一職責原則,類的設計儘量做到單一職責原則 擴展:單一職責原則同 ...
  • 困擾 Intellij idea是一款非常強大的編輯器,可以很方便地幫我們創建maven項目,有用過的同學應該都深有體會,但我們經常會遇到一個困擾,那就是用idea創建maven項目時,速度很慢,往往需要好幾分鐘的時間,有時甚至會卡住,主要原因是創建maven項目時預設是下載求網路上的一個文件arc ...
  • 如果這是第二次看到我的文章,歡迎右側掃碼訂閱我喲~ 👉 本文長度為3012字,建議閱讀8分鐘。 堅持原創,每一篇都是用心之作~ 下麵的這個場景你可能會覺得很熟悉(Z哥我又要出演了): Z哥:@All 兄弟姐妹們,這次我這邊有個需求需要給「商品上架」增加一道審核,會影響到大家和我交互的介面。大家抽空 ...
  • 1 初步認識 適配器模式的定義 將一個類的介面轉成客戶期望的另外一個介面。適配器模式使得原本由於介面不匹配而不能一起工作的那些類可以一起工作。 大白話 適配器模式就像旅行插座轉換器(圖1)、Type-c轉VGA轉介面(圖4)一樣。 圖1. 圖片來源網路 圖2. 圖片來源網路 去過香港迪拜等的同學都知 ...
  • Nginx 介紹:高性能的http伺服器和反向代理(請求通過反向代理之後,訪問伺服器端的邏輯)如下圖所示: Ningx的作用 負載均衡 所謂負載就是伺服器各項技術所承受的壓力 均衡,平均分配壓力(物理平均,邏輯平均) 通過輪訓機制來達到物理均衡 動靜分離 伺服器可以處理動態資源(tomcat jsp ...
  • 前言:流程實現基本流轉功能外,通常也需要調用外部事件,用於和業務系統的交互,同時存儲一些流程變數,用於追蹤和記錄業務數據變化對流程流轉的影響。 1. 流程事件 流程執行過程中,伴隨各種事件的發生,而且是存在於整個流程的生命周期,即從流程啟動一直到流程結束的整個過程都有事件發生。這些事件的發生,業務系 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...