Java 裝飾器模式詳解

来源:http://www.cnblogs.com/zhaoyanjun/archive/2017/02/24/6439594.html
-Advertisement-
Play Games

轉載請註明出處:http://blog.csdn.net/zhaoyanjun6/article/details/56488020 前言 在上面的幾篇文章中,著重介紹了Java 中常見的 IO 相關知識,在學習的過程中,發現 IO 包中是用了大量的裝飾器模式,為了徹底的學習 IO,今天就來揭開裝飾器 ...


轉載請註明出處:http://blog.csdn.net/zhaoyanjun6/article/details/56488020

 

前言

在上面的幾篇文章中,著重介紹了Java 中常見的 IO 相關知識,在學習的過程中,發現 IO 包中是用了大量的裝飾器模式,為了徹底的學習 IO,今天就來揭開裝飾器模式的面紗。

為了弄明白裝飾器模式的本質,我查看了很多資料,發現有很多文章要麼說的很苦澀,要麼舉的例子不恰當。

其實我們可以這樣理解裝飾器模式, 就拿自己舉例子,你把自己裸體的樣子,想象成被裝飾的對象。你的鞋子,你的寸衣,你的外套,你的手錶,你的帽子 等等,都是你的裝飾物,你和這些裝飾物,是裝飾和被裝飾的關係。

 

實例展示

好了,現在我們用代碼的方法去理解這樣概念。

首先,我們發現,不管是裸體的人,還是你的鞋子、帽子,都有展示的功能,我們稱之為show 方法。

我們定義一個介面,它具有展示的功能,也就是show() , 

package com.user;

/**
 * 定義介面
 * @author T
 *
 */
public interface AbstractPerson {

    //具有展示的功能
    void show() ;
}

 

現在應該定義一個裸體的自己了,Me 類

package com.user;

/**
 * 定義一個具體的人,就是被裝飾者
 * @author T
 *
 */
public class Me implements AbstractPerson {

    @Override
    public void show() {
        System.out.println( "什麼都沒穿,我展示的是裸體");
    }

}

 

下麵該定義,鞋子,帽子,手錶等 裝飾物,等等先別急,我們應該先定義一個鞋子,帽子,手錶的抽象父類 AbstractClothes 。 其實抽象的父類有一個構造函數,構造函數裡面的參數是抽象的人類,這裡的用法很巧妙,這也是能夠實現裝飾功能的一個必不可少的步驟。

package com.user;

/**
 * 定義抽象裝飾物
 * @author T
 *
 */
public abstract class AbstractClothes implements AbstractPerson {

    AbstractPerson abstractPerson ;

    public AbstractClothes( AbstractPerson abstractPerson ){
        this.abstractPerson = abstractPerson ;
    }

    @Override
    public void show() {
        abstractPerson.show();
    }

}

 

下麵開始定義,帽子裝飾物  Hat 類, 繼承 AbstractClothes 類

package com.user;

/**
 * 帽子裝飾物
 * @author T
 *
 */
public class Hat extends AbstractClothes {

    public Hat(AbstractPerson abstractPerson) {
        super(abstractPerson);
    }
    
    @Override
    public void show() {
        super.show();
        say();
    }
    
    public void say(){
        System.out.println( "我展示一個帽子");
    }

}

 

定義鞋子裝飾類 Shoes ,   繼承 AbstractClothes 類

package com.user;

/**
 * 鞋子裝飾物
 * @author T
 *
 */
public class Shoes extends AbstractClothes {

    public Shoes(AbstractPerson abstractPerson) {
        super(abstractPerson);
    }
    
    @Override
    public void show() {
        super.show();
        say();
    }
    
    public void say(){
        System.out.println( "我展示一雙鞋子");
    }
}

 

創建測試類 Test

package com.user;

public class Test {

    public static void main(String[] args) {

        //創建被裝飾者
        Me me = new Me() ;

        //裸體的人被裝飾了帽子 ,具有了展示帽子的能力
        Hat hat = new Hat( me ) ;

        // 帶了帽子的人被裝飾了鞋子,具有了展示鞋子的本領
        Shoes shoes = new Shoes( hat ) ;

        shoes.show();
    }
}

 運行結果:

什麼都沒穿,我展示的是裸體
我展示一個帽子
我展示一雙鞋子

裝飾器模式的類圖

在學習完了一個小例子之後,我們試著總結出裝飾器模式的類圖。

裝飾器模式類圖:

 

  • Component抽象構件角色:真實對象和裝飾對象有相同的介面。這樣,客戶端對象就能夠以與真實對象相同的方式同裝飾對象交互。
  • ConcreteCompoent具體構建角色(真實對象):定義一個將要接收附加責任的類。
  • Decorator裝飾角色:持有一個抽象構件的引用。裝飾對象接受所有客戶端的請求,並把這些請求轉發給真實的對象。這樣,就能在真實對象調用前後增加新的功能。
  • ConcreteDecorate具體裝飾角色:負責給構件對象增加新的功能。

 

裝模式在Java I/O庫中的應用

IO流實現細節:

  • Component抽象構件角色:io流中的InputStream,OutputStream,Reader,Writer
  • ConcreteComponent具體構件角色:io流中的FileInputStream,FileOutputStream
  • Decorate裝飾角色:持有抽象構件的引用,FilterInputStream,FilterOutputStream
  • ConcreteDecorate具體裝飾角色:負責給構件對象添加新的責任,BufferedInputStream,BufferedOutputStream等

 

優點

  •  擴展對象功能,比繼承靈活,不會導致類個數急劇增加。
  • 可以對一個對象進行多次裝飾,創造出不同行為的組合,得到功能更加強大的對象。
  • 具體構件類和具體裝飾類可以獨立變化,用戶可以根據需要自己增加新的 具體構件子類和具體裝飾子類。

 

缺點

  • 產生很多小對象。大量小的對象占據記憶體,一定程度上影響性能。
  • 裝飾模式易出錯,調試排查比較麻煩。
 

總結

  • 裝飾模式(Decorate)也叫包裝模式(Wrapper)
  • 裝飾模式降低系統的耦合度,可以動態的增加或刪除對象的責任,並使得需要裝飾的具體構建類和具體裝飾類可以獨立變化,以便增加新的具體構建類和具體裝飾類。

 

參考資料:

Java設計模式學習09——裝飾模式

Java與模式:裝飾(Decorator)模式

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • package com.example.lesson3_4; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Intent; import a... ...
  • package com.lxj.lesson2_3ID19; import com.example.lesson2_3_id19.R; import com.lxj.other.AgeActivity; import com.lxj.other.HeightActivity; import com.... ...
  • 在Adapter的itemView裡面,判斷列表是否在滾動中,其實是比較麻煩的,可能耦合性會比較嚴重。 所以考慮了下,是否能在itemView裡面,檢測列表的滾動狀態,並監聽停止狀態載入圖片,實現itemView與Adapter進而與ListView等解耦呢? 想到了一種實現方法,直接上代碼了: 使 ...
  • 1、首先創建一個按鈕 <Button android:id="@+id/click" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="點擊變色" android:backgro ...
  • 1、 請描述下Activity的生命周期。 activity的生命周期方法有: onCreate()、onStart()、onReStart()、onResume()、onPause()、onStop()、on Destory(); 可見生命周期:從onStart()直到系統調用onStop() 前 ...
  • 在將自己寫的工具打成.jar包的時候,有時候會需要引用到res中的資源,這時候不能將資源一起打包,只能通過反射機制動態的獲取資源. 特別用在自己定義一個工具將其打成.jar包時,特別註意資源的獲取 1、封裝成一個工具類 2、資源的獲取 3.java ...
  • 使用介紹 開發中經常會遇到一些和倒計時有關的場景,比如發送驗證碼的按鈕,會在點擊發送後,顯示倒計時間,倒計時結束後才能夠刷新按鈕,再次允許點擊。為了不阻塞軟體的運行,又要實時刷新界面,我們通常會用到 Handler 或者 AsyncTask 等技術,自己寫邏輯實現。其實 Android 中已經封裝好 ...
  • iOS指紋解鎖 1、首先,引入依賴框架 LocalAuthentication.framework 2、然後,判斷系統是否為iOS8及以上 3、最後,在APP啟動時調用以下方法即可完成指紋解鎖的全部功能集成 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...