設計模式精講 Day 8:組合模式(Composite Pattern)

【設計模式精講 Day 8】組合模式(Composite Pattern)


開篇

在“設計模式精講”系列的第8天,我們將深入講解組合模式(Composite Pattern)。組合模式是一種結構型設計模式,它允許將對象組合成樹形結構以表示“整體-部分”的層次關系。通過這種模式,客戶端可以統一地處理單個對象和對象組合,從而簡化了復雜結構的操作。

組合模式的核心思想是:將對象組織成樹狀結構,使得客戶端無需區分是處理單個對象還是對象集合。這在文件系統、菜單系統、圖形界面等需要層級結構的場景中非常常見。

本文將從模式定義、結構、適用場景、實現方式、工作原理、優缺點分析等方面全面解析組合模式,并結合實際代碼和案例說明其在Java開發中的應用價值。


模式定義

組合模式(Composite Pattern) 是一種結構型設計模式,它允許你將對象組合成樹形結構以表示“整體-部分”的層次結構。組合模式讓客戶端可以統一地處理單個對象和對象組合,而無需關心它們的具體類型。

核心思想是:

  • 將對象組織成樹狀結構
  • 客戶端可以一致地操作單個對象和對象組合
  • 通過遞歸結構簡化復雜系統的管理

模式結構

組合模式通常包含以下幾個關鍵角色:

角色名稱說明
Component定義對象的公共接口,既可以是葉子節點,也可以是容器節點
Leaf葉子節點,不包含子節點,直接實現Component接口
Composite容器節點,包含多個Component子節點,實現對子節點的增刪改查操作

UML類圖文字描述

  • Component 是抽象類或接口,定義了所有節點共有的方法。
  • LeafComponent 的具體實現,代表葉子節點。
  • Composite 也是 Component 的具體實現,但內部維護了一個 List<Component> 來保存子節點。

適用場景

組合模式適用于以下幾種典型場景:

場景描述
文件系統文件夾與文件的嵌套結構,如Windows資源管理器
圖形用戶界面菜單項、子菜單、主菜單的層級結構
組織架構公司部門、子公司、員工的層級關系
表達式求值數學表達式的樹形結構,如算術運算符的組合
配置管理多層配置項的組合結構,如XML/JSON解析

實現方式

下面是一個完整的Java實現示例,展示了如何用組合模式構建一個簡單的文件系統模型。

import java.util.ArrayList;
import java.util.List;// Component 接口
interface FileSystemNode {void display(int depth);
}// Leaf 類:文件
class File implements FileSystemNode {private String name;public File(String name) {this.name = name;}@Overridepublic void display(int depth) {// 輸出縮進for (int i = 0; i < depth; i++) {System.out.print("  ");}System.out.println("File: " + name);}
}// Composite 類:文件夾
class Folder implements FileSystemNode {private String name;private List<FileSystemNode> children = new ArrayList<>();public Folder(String name) {this.name = name;}public void add(FileSystemNode node) {children.add(node);}public void remove(FileSystemNode node) {children.remove(node);}@Overridepublic void display(int depth) {// 輸出當前文件夾名稱for (int i = 0; i < depth; i++) {System.out.print("  ");}System.out.println("Folder: " + name);// 遞歸輸出子節點for (FileSystemNode child : children) {child.display(depth + 1);}}
}

使用示例

public class CompositePatternDemo {public static void main(String[] args) {// 創建根目錄Folder root = new Folder("Root");// 創建子文件夾Folder documents = new Folder("Documents");Folder pictures = new Folder("Pictures");// 添加文件documents.add(new File("report.docx"));documents.add(new File("notes.txt"));pictures.add(new File("photo1.jpg"));pictures.add(new File("photo2.jpg"));// 將子文件夾添加到根目錄root.add(documents);root.add(pictures);// 顯示整個結構root.display(0);}
}

單元測試(JUnit 5 示例)

import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.*;class CompositePatternTest {@Testvoid testFileSystemStructure() {Folder root = new Folder("Root");Folder documents = new Folder("Documents");Folder pictures = new Folder("Pictures");documents.add(new File("report.docx"));documents.add(new File("notes.txt"));pictures.add(new File("photo1.jpg"));pictures.add(new File("photo2.jpg"));root.add(documents);root.add(pictures);assertNotNull(root);assertEquals(2, root.children.size());}
}

工作原理

組合模式通過遞歸結構來處理復雜的層次結構。其底層機制如下:

  1. 統一接口:無論是葉子節點還是容器節點,都實現了相同的接口(FileSystemNode),因此客戶端可以統一調用 display() 方法。
  2. 遞歸遍歷:當訪問一個容器節點時,會遞歸地訪問其子節點,直到所有節點都被處理。
  3. 隱藏復雜性:客戶端不需要知道當前操作的是單個對象還是對象集合,只需調用相同的方法即可。

優缺點分析

優點缺點
簡化客戶端代碼,統一處理單個對象和組合對象增加了系統的復雜性,可能造成過度設計
便于擴展,新增節點類型只需繼承Component需要確保每個子類正確實現接口方法
提高代碼復用性,避免重復代碼對于簡單結構可能顯得冗余

案例分析:企業級文件管理系統

在某企業的文件管理系統中,用戶需要查看和管理多級文件夾結構。該系統使用組合模式構建了以下結構:

  • 根目錄(Root)
  • 多個一級文件夾(如“項目A”、“項目B”)
  • 每個項目文件夾下有二級文件夾(如“文檔”、“代碼”、“圖片”)
  • 每個二級文件夾中包含具體的文件

問題描述

傳統做法是為每種類型的節點編寫不同的處理邏輯,導致代碼臃腫且難以維護。

解決方案

采用組合模式后,系統通過統一的 FileSystemNode 接口進行操作,無論當前處理的是文件還是文件夾,都可以使用相同的 display() 方法進行顯示,極大簡化了代碼邏輯。


與其他模式的關系

組合模式常與其他設計模式配合使用,例如:

模式用途關聯方式
迭代器模式遍歷組合結構中的元素可以在Composite中加入Iterator接口
訪問者模式對組合結構中的元素進行操作訪問者可以訪問Composite及其子節點
裝飾器模式動態地給對象添加職責在Composite基礎上動態增強功能
策略模式支持不同行為的切換可用于Composite中子節點的行為控制

總結

今天學習了組合模式(Composite Pattern),它是一種結構型設計模式,能夠將對象組織成樹形結構,使客戶端可以統一處理單個對象和對象組合。我們從模式定義、結構、適用場景、實現方式、工作原理、優缺點分析等方面進行了詳細講解,并提供了完整的Java代碼示例。

組合模式在文件系統、圖形界面、配置管理等場景中廣泛應用,體現了面向對象設計原則中的單一職責原則開閉原則,同時支持靈活的擴展。


下一講預告

明天我們將進入行為型模式的第一天,講解責任鏈模式(Chain of Responsibility Pattern)。該模式通過將請求的發送者和接收者解耦,使得多個對象都有機會處理請求,形成一條處理鏈。


文章簡述

本文系統講解了設計模式中的組合模式(Composite Pattern),從理論到實踐,全面剖析了其核心思想、結構組成、適用場景以及Java實現方式。通過構建一個文件系統模型,展示了組合模式如何將對象組織成樹形結構,并統一處理單個對象和對象組合。文章還結合真實項目案例,說明了組合模式在實際開發中的價值,并與其他設計模式進行了對比分析。最后,總結了該模式的優缺點及適用范圍,幫助開發者在實際項目中合理運用這一設計模式。


進一步學習資料

  1. Design Patterns: Elements of Reusable Object-Oriented Software - GoF經典著作
  2. Refactoring Guru - Composite Pattern
  3. Java Design Patterns - Composite Pattern
  4. GeeksforGeeks - Composite Design Pattern in Java
  5. Wikipedia - Composite pattern

核心設計思想總結

組合模式的核心思想是將對象組織成樹形結構,使客戶端可以統一處理單個對象和對象組合。在實際項目中,它特別適合處理具有層級結構的業務場景,如文件系統、菜單系統、圖形界面等。通過組合模式,我們可以提高代碼的可維護性和擴展性,避免重復代碼,提升系統的靈活性和可讀性。

在實際開發中,建議在遇到需要處理“整體-部分”關系的場景時優先考慮組合模式。結合其他設計模式(如迭代器、訪問者)可以進一步增強其功能,使其更適應復雜業務需求。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/910017.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/910017.shtml
英文地址,請注明出處:http://en.pswp.cn/news/910017.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Dify學習筆記】:RagFlow接入Dify基礎教程

RagFlow接入Dify基礎教程 如果RagFlow還沒部署&#xff0c;可參考我另一篇本地部署文章&#xff1a;【Dify學習筆記】&#xff1a;本地部署RagFlow適配Dify 一、RagFlow 1. 配置模型 點擊&#xff1a;頭像 > Model providers 添加模型供應商、設置默認模型Set default …

Apache ECharts-02.入門案例

一.入門案例 官網下載&#xff1a;下載 - Apache ECharts&#xff0c;下載echarts.js文件&#xff0c;下載好后在其同一個文件夾下創建html文件即可。 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>ECharts</title…

社群經濟視閾下開源AI智能名片鏈動2+1模式與S2B2C商城小程序在私域電商中的融合應用研究

摘要&#xff1a;在數字經濟與社交網絡深度融合的背景下&#xff0c;付費社群憑借精準用戶篩選、高價值成員聚合及強信任關系鏈等優勢&#xff0c;成為私域電商發展的核心載體。本文基于社群經濟理論&#xff0c;結合“開源AI智能名片鏈動21模式S2B2C商城小程序”的技術與商業邏…

【Tools】Mac brew工具

Homebrew&#xff08;簡稱 brew&#xff09;是 macOS&#xff08;也支持 Linux&#xff09;上的一款 包管理工具&#xff0c;它的作用類似于&#xff1a; Ubuntu 下的 aptCentOS 下的 yumArch Linux 下的 pacman 一句話概括&#xff1a; brew 是用來在 macOS 上安裝、管理軟件…

IEEE RAL 雙臂機器人三連抓估計物體狀態 無需特制夾爪或視覺相機 - 大阪大學萬偉偉老師團隊

IEEE RA-L | 萬偉偉老師團隊提出雙臂機器人規劃控制方法有效降低被抓物姿態不確定性 日本大阪大學萬偉偉老師團隊針對雙臂機器人開發了一種重復抓取規劃和阻抗控制的方法&#xff0c;該方法通過兩個機械臂依次尋找抓取位置和物體姿態&#xff0c;并通過三個正交抓取動作&#x…

AtomicInteger 和 volatile Integer對比

AtomicInteger 和 volatile Integer 雖然都與線程安全有關&#xff0c;但本質完全不同。它們的主要區別體現在原子性保證和功能上&#xff1a; &#x1f50d; 核心區別對比表 特性volatile IntegerAtomicInteger原子性? 不保證復合操作原子性? 保證所有操作的原子性自增操作…

一生一芯 PA2 RTFSC

從src/isa/riscv32/inst.c出發。 向上搜索&#xff0c;理解宏定義的含義。 R(i) #define R(i) gpr(i) R(i)&#xff1a;訪問第i號通用寄存器 會被替換為&#xff1a; #define gpr(idx) (cpu.gpr[check_reg_idx(idx)]) 分為兩個部分&#xff1a; cpu.gprcheck_reg_idx c…

深度學習——手寫數字識別

深度學習——手寫數字識別 學習深度學習的朋友應該對MNIST數據集不陌生吧&#xff0c;相信很多人在剛開始學習深度學習的時候都會用到MNIST數據集進行書寫數字識別。本篇文章參考魚書創建一個深度網絡來進行書寫數字識別的任務。 如上圖所示&#xff0c;這里使用的卷積層全都是…

HashMap算法高級應用實戰:頻率類子數組問題的5種破解模式

本文將深入剖析5種基于HashMap的高級模式&#xff0c;通過原理詳解、多語言實現、性能對比和工業級應用&#xff0c;助您徹底掌握頻率類子數組問題。 1. 深入解析&#xff1a;頻率類子數組問題 1.1 問題定義與分類 頻率類子數組問題是指需要統計或查找滿足特定元素頻率條件的…

【精選】計算機畢業設計HTML5智能寵物尋找與領養系統 跨平臺寵物匹配 地圖定位找寵 領養申請審核系統源碼+論文+PPT+講解

博主介紹&#xff1a; ?我是阿龍&#xff0c;一名專注于Java技術領域的程序員&#xff0c;全網擁有10W粉絲。作為CSDN特邀作者、博客專家、新星計劃導師&#xff0c;我在計算機畢業設計開發方面積累了豐富的經驗。同時&#xff0c;我也是掘金、華為云、阿里云、InfoQ等平臺…

拼多多商家端 anti_content 補環境分析

聲明 本文章中所有內容僅供學習交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包內容、敏感網址、數據接口等均已做脫敏處理&#xff0c;嚴禁用于商業用途和非法用途&#xff0c;否則由此產生的一切后果均與作者無關&#xff01; 部分python代碼 import execjs impor…

電腦、手機長時間不關機可以嗎

電腦和手機常年處于開機狀態&#xff0c;只有在沒電或者系統提示更新的時候才會關機。那問題來了&#xff0c;電腦、手機長時間不關機到底可不可以呢&#xff1f;今天咱們就來好好嘮嘮。 手機長時間不關機的情況 先來說說手機。現在的智能手機功能越來越強大&#xff0c;我們…

「AI大數據」| 《華為:面向智能制造的工業大模型標準化研究報告》

今天給大家介紹 《華為:面向智能制造的工業大模型標準化研究報告》&#xff0c;這是一份由中國電子技術標準化研究院聯合華為等多家企業編寫的權威報告&#xff0c;聚焦工業大模型在智能制造領域的標準化發展。報告詳細分析了工業大模型的技術架構、應用場景、標準化現狀與挑戰…

Dinky1.2.3基于Kubernetes Application模式提交Flink作業

前言 Dinky 是一個開箱即用、易擴展&#xff0c;以 Apache Flink 為基礎&#xff0c;連接 OLAP 和數據湖等眾多框架的一站式實時計算平臺&#xff0c;致力于流批一體和湖倉一體的探索與實踐。 致力于簡化Flink任務開發&#xff0c;提升Flink任務運維能力&#xff0c;降低Flink…

【軟考高級架構設計師】——2025年上半年軟考真題(回憶版)

目錄 一、綜合知識1.1、計算機基礎與操作系統(15道單選)1.2、軟件工程與架構(16道單選)1.3、數據與網絡(8道單選)1.4、數學與邏輯(4道單選)1.5、其他(27道單選)1.6、英文題(質量屬性)(5道單選)二、案例分析2.1、大模型訓練系統(必選題)2.2、醫院知識圖譜(可選…

哈夫曼樹Python實現

哈夫曼樹構建原則&#xff1a; .統計頻率&#xff1a;對待編碼字符&#xff08;或數據塊&#xff09;的頻率進行統計。.初始化森林&#xff1a;將每個字符視為一棵只有根節點的二叉樹&#xff0c;權值為頻率。.合并樹&#xff1a;重復以下操作&#xff0c;直到只剩一棵樹&…

Dockerfile的學習與實踐

Dockerfile通過一系列的命令和參數&#xff0c;構建自定義鏡像。一般步驟如下&#xff1a; 一. 常用命令說明 基礎命令具體命令描述例子FROMFROM[基礎鏡像:版本號]基于指定的基礎鏡像構建自定義鏡像FROM eclipse-temurin:17-jdk-alpineRUNRUN構建容器需要運行的命令&#xff0…

【三大前端語言之一】靜態網頁語言:HTML詳解

你知道你在瀏覽器中所看到的每一個按鈕&#xff0c;每一個框&#xff0c;都是怎么創造出來的嗎&#xff1f;它們并非魔法&#xff0c;而是由一種被稱為HTML的語言精心構建的骨架。作為前端世界的三大基石之一&#xff08;HTML、CSS、JavaScript&#xff09;&#xff0c;HTML是萬…

04、誰發明了深度學習的方法,是怎么發明的?

深度學習的發展是多位研究者長期探索的結果,其核心方法的形成并非由單一人物 “發明”,而是歷經數十年理論積累與技術突破的產物。以下從關鍵人物、核心技術突破及歷史背景三個維度,梳理深度學習方法的起源與發展脈絡: 一、深度學習的奠基者與關鍵貢獻者 1. Geoffrey Hin…

Jmeter ServerAgent在arm環境啟動報錯no libsigar-aarch64-linux.so in java.library.path

使用Jmeter壓測的時候&#xff0c;用ServerAgent監測arm服務器的性能指標&#xff0c;在啟動ServerAgent時&#xff0c;報錯了&#xff1a;no libsigar-aarch64-linux.so in java.library.path 解決方案&#xff1a; 下載libsigar-aarch64-linux.so文件&#xff0c;放置在Serv…