初識設計模式 - 組合模式

来源:https://www.cnblogs.com/fatedeity/archive/2022/10/11/16778064.html
-Advertisement-
Play Games

組合設計模式(Composite Design Pattern)其應用場景非常特殊,主要用於處理樹形結構數據,它可以讓葉子對象和容器對象的使用具有一致性。 ...


簡介

組合模式就是組合多個對象形成樹形結構以表示具有“部分 - 整體”關係的層次結構。組合模式對單個對象(葉子對象)和組合對象(容器對象)的使用具有一致性。

組合模式的關鍵是定義一個抽象構件類,它既可以代表葉子,也可以代表容器。客戶端針對該抽象構件進行編程,無需知道它到底表示的是葉子還是容器,可以對其進行統一處理。

具體實現

對於組合模式的抽象構件角色,其代碼示例如下:

public abstract class Component {
    // 增加成員
    public abstract void add(Component c);

    // 刪除成員
    public abstract void remove(Component c);

    // 獲取成員
    public abstract Component getChild(int i);

    // 業務方法
    public abstract void operation();
}

如果繼承抽象構件類的是葉子構件,其代碼示例如下:

public class Leaf extends Component {
    @Override
    public void add(Component c) {
        // 增加成員
        // 異常處理或業務提示
    }

    @Override
    public void remove(Component c) {
        // 刪除成員
        // 異常處理或業務提示
    }

    @Override
    public Component getChild(int i) {
        // 獲取成員
        // 異常處理或業務提示
    }

    @Override
    public void operation() {
        // 業務方法
        // 葉子構件具體業務方法的實現
    }
}

如果繼承抽象構件類的是容器構件,其代碼示例如下:

import java.util.ArrayList;

public class Composite extends Component {  
    private final ArrayList<Component> list = new ArrayList<>();  
  
    @Override  
    public void add(Component c) {  
        // 增加成員  
        list.add(c);  
    }  
  
    @Override  
    public void remove(Component c) {  
        // 刪除成員  
        list.remove(c);  
    }  
  
    @Override  
    public Component getChild(int i) {  
        // 獲取成員  
        return (Component) list.get(i);  
    }  
  
    @Override  
    public void operation() {  
        // 業務方法  
        // 葉子構件具體業務方法的實現  
        // 遞歸調用成員構件的業務方法  
        for (Component obj : list) {  
            obj.operation();  
        }  
    }  
}

分類

在使用組合模式時,根據抽象構件類的定義形式,可以將組合模式分為透明組合模式和安全組合模式兩種。

透明組合模式

在透明組合模式中,抽象構件類聲明瞭所有用於管理成員的方法,如 add()remove()getChild() 等所有方法。

透明組合模式也是組合模式的標準形式,這樣做的好處是確保所有的構件類都使用相同的介面。

其缺點就是不夠安全,因為葉子對象和容器對象有本質上的區別,對葉子對象提供 add()remove()getChild() 等方法是沒有意義的,如果沒有提供相應的錯誤處理代碼,在運行階段有可能會出錯。

安全組合模式

在安全組合模式中,抽象構件類沒有聲明任何管理成員的方法,只聲明抽象的業務方法。

這樣的做法是安全的,因為根本不向葉子對象提供這些管理成員對象的方法,對於葉子對象,客戶端不可能調用到這些方法。

相對的,其缺點就是不夠透明,因為葉子構件和容器構件具有不同的方法,客戶端不能完全針對抽象編程,必須有區別地對待葉子構件和容器構件。

總結

優點

組合模式的主要優點如下:

  • 組合模式為樹形結構的面向對象實現提供了一種靈活的解決方案
  • 在組合模式中增加新的葉子構件和容器構件都很方便,符合開閉原則
  • 客戶端可以一致地使用一個組合結構或其中單個對象,簡化了客戶端代碼

缺點

組合模式的主要缺點如下:

  • 設計較複雜,客戶端需要花費更多時間理清類之間的層次關係
  • 在增加新構件時很難對容器中的構件類型進行限制,通常通過運行時進行類型檢查來實現

適用場景

組合模式的適用場景如下:

  • 在具有整體和部分的層次結構中,希望通過一種方式忽略整體和部分的差異
  • 在一個使用面向對象語言開發的系統中需要處理一個樹形結構

源碼

在 JDK 中,HashMap 也是用到了組合模式,如下是部分代碼:

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

    public void putAll(Map<? extends K, ? extends V> m) {
        putMapEntries(m, true);
    }

    final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
        int s = m.size();
        if (s > 0) {
            if (table == null) { // pre-size
                float ft = ((float)s / loadFactor) + 1.0F;
                int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                         (int)ft : MAXIMUM_CAPACITY);
                if (t > threshold)
                    threshold = tableSizeFor(t);
            } else {
                // Because of linked-list bucket constraints, we cannot
                // expand all at once, but can reduce total resize
                // effort by repeated doubling now vs later
                while (s > threshold && table.length < MAXIMUM_CAPACITY)
                    resize();
            }

            for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
                K key = e.getKey();
                V value = e.getValue();
                putVal(hash(key), key, value, false, evict);
            }
        }
    }
}

putAll()putMapEntries() 都接受一個 Map 結構參數,這個 Map 就是一個抽象構件,HashMap 同樣是實現了 Map 結構,輕易實現一個樹形的調用結構。

首發於翔仔的個人博客,點擊查看更多。


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

-Advertisement-
Play Games
更多相關文章
  • iOS ViewController 寫UIKit的代碼, ViewController是離不開的. 本文試圖講講它的基本知識, 不是很深入且有點雜亂, 供初級選手和跨技術棧同學參考. What is a View Controller iOS中的View Controller非常像Android中 ...
  • 雖然xcode現在可以免證書進行測試了,但眾多跨平臺開發者,如果還沒註冊蘋果開發者賬號。 想安裝到自己非越獄手機測試是無能為力了。 不過新技術來了,只需要普通免費的蘋果賬號無需付費成為開發者就可以申請iOS證書打包ipa安裝到自己手機測試! 沒付費蘋果開發者賬號的,也能輕鬆調試自己的蘋果APP。 當 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 第一題:說一下這三個div的佈局 <div class="parent"> <div class="child1">child1 content</div> <div class="child2">child2 content</div> ...
  • 1、將項目里的“node_modules”文件夾刪除,一般“node_modules”文件夾太大,一般不會打包上傳到svn、git上的,所以沒有這個文件夾就不用刪。 2、刪除package-lock.json。它是基於項目作者的npm版本庫生成的,如果不刪掉這個依賴文件,容易出現npm版本差異導致的 ...
  • 觀察者模式也可以理解為:發佈訂閱模式 發佈者狀態更新,通過管道介面實現訂閱者動態更新 1 class Middleware: 2 """ 3 發佈者和訂閱者交互類 4 0、訂閱者容器列表 5 1、包括訂閱者的增加、刪除 6 2、通過管道通知訂閱者 7 """ 8 9 def __init__(sel ...
  • 下午我被叫去參加“合作服務商資金安全解決方案”項目的codereview。對程式實現邏輯上存疑。簡單聽他們瞭解了一下需求邏輯。然後,果然發現邏輯有疏漏。為了表達清楚我的意思,上草圖。邊“畫”邊講。然後,大家點頭默許:還是戰哥想的全面! 在我們日常開發討論過程中,總會出現這樣的情況,你在講的頭頭是道, ...
  • 決策引擎是風控的大腦,而決策樹的編排能力和體驗是構建大腦的手段,如何構建高效、絲滑、穩定可靠的決策樹編排能力,是對風控決策引擎的一大挑戰,本篇文章和大家分享一下過往構建心得。 ...
  • 我們都知道Spring中IOC是使用的工廠模式,但是對於實現細節就一知半解了,今天這篇文章就帶大家解讀Spring中是如何使用工廠模式的。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...