【設計模式-3.7】結構型——組合模式

說明:本文介紹結構型設計模式之一的組合模式

定義

組合模式(Composite Pattern)又叫作整體-部分(Part-Whole)模式,它的宗旨是通過將單個對象(葉子節點)和組合對象(樹枝節點)用相同的接口進行表示,使得客戶對單個對象和組合對象的使用具有一致性,屬于結構型設計模式。(引自《設計模式就該這樣學》P263)

文件系統

以文件系統為例,如下,是服務器上某個文件夾的文件結構,該文件夾下既有文件夾,也有文件

在這里插入圖片描述

如果我要構建這樣一個文件夾-文件系統,代碼應該是這樣寫的,如下:

(圖片文件,ImageFile)

/*** 圖片文件*/
public class ImageFile {/*** 圖片名稱*/private String name;public ImageFile(String name) {this.name = name;}/*** 展示*/public void show(int space) {for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);}
}

(電影文件,MovieFile)

/*** 電影文件*/
public class MovieFile {/*** 電影名稱*/private String name;public MovieFile(String name) {this.name = name;}/*** 展示*/public void show(int space) {for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);}
}

(文件夾,Folder,定義多個文件集合,并開放對應的增加方法)

import java.util.ArrayList;/*** 文件夾*/
public class Folder {/*** 文件夾名稱*/private String name;/*** 文件夾下的文件夾*/private ArrayList<Folder> folders = new ArrayList<>();/*** 文件夾下的圖片文件*/private ArrayList<ImageFile> imageFiles = new ArrayList<>();/*** 文件夾下的視頻文件*/private ArrayList<MovieFile> movieFiles = new ArrayList<>();public Folder(String name) {this.name = name;}/*** 添加文件夾*/public void addFolder(Folder folder) {folders.add(folder);}/*** 添加圖片文件*/public void addImageFile(ImageFile imageFile) {imageFiles.add(imageFile);}/*** 添加電影文件*/public void addMoveFile(MovieFile movieFile) {movieFiles.add(movieFile);}/*** 展示*/public void show(int space) {// 打印文件夾space++;for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);for (Folder folder : folders) {folder.show(space);}// 打印圖片文件space++;for (ImageFile imageFile : imageFiles) {imageFile.show(space);}// 打印電影文件space++;for (MovieFile movieFile : movieFiles) {movieFile.show(space);}}
}

(客戶端使用,Client)

public class Client {public static void main(String[] args) {// 頂級文件夾Folder folder = new Folder("folder");// 二級文件夾Folder images = new Folder("images");Folder movies = new Folder("movies");// 三級目錄下的文件ImageFile boy = new ImageFile("boy.png");ImageFile girl = new ImageFile("girl.png");images.addImageFile(boy);images.addImageFile(girl);// 三級文件夾Folder director1 = new Folder("heizeming");Folder director2 = new Folder("xiaolinzhengshu");// 四級目錄MovieFile movieFile1 = new MovieFile("luoshengmen.mp4");MovieFile movieFile2 = new MovieFile("qiwushi.mp4");director1.addMoveFile(movieFile1);director1.addMoveFile(movieFile2);MovieFile movieFile3 = new MovieFile("duomingjian.mp4");MovieFile movieFile4 = new MovieFile("qiefu.mp4");director2.addMoveFile(movieFile3);director2.addMoveFile(movieFile4);movies.addFolder(director1);movies.addFolder(director2);// 文件夾添加到頂級文件夾folder.addFolder(images);folder.addFolder(movies);folder.show(0);}
}

運行,hora!(看!),能實現目的

在這里插入圖片描述

但這里存在問題,文件系統,簡單來說只有文件夾和文件兩個實體對象,代碼中的圖片文件、電影文件可以抽象為文件(File),這是整體與個體的場景。

組合模式

使用組合模式改進上述代碼,如下:

(抽象節點類,Node)

/*** 抽象節點*/
public abstract class Node {/*** 節點名稱*/protected String name;public Node(String name) {this.name = name;}/*** 添加節點*/protected abstract void add(Node node);/*** 展示*/protected void show(int space) {for (int i = 0; i < space; i++) {System.out.print(" ");}System.out.println(name);}/*** 重載方法,使用的時候就不用給參數了*/protected void show() {show(0);}
}

(文件夾,Folder)

import java.util.ArrayList;/*** 文件夾*/
public class Folder extends Node {/*** 文件夾下的子節點*/private ArrayList<Node> childrenNodes = new ArrayList<>();/*** 調用父類的構造方法*/public Folder(String name) {super(name);}@Overrideprotected void add(Node node) {childrenNodes.add(node);}@Overrideprotected void show(int space) {super.show(space);space++;for (Node node : childrenNodes) {node.show(space);}}
}

(文件,File)

/*** 文件*/
public class File extends Node {/*** 調用父類的構造方法*/public File(String name) {super(name);}@Overrideprotected void add(Node node) {System.out.println("不能添加子節點");}@Overrideprotected void show(int space) {super.show(space);}
}

(客戶端使用,Client)

public class Client {public static void main(String[] args) {// 頂級文件夾Folder folder = new Folder("folder");// 二級文件夾Folder images = new Folder("images");Folder movies = new Folder("movies");// 三級目錄下的文件File boy = new File("boy.png");File girl = new File("girl.png");images.add(boy);images.add(girl);// 三級文件夾Folder director1 = new Folder("heizeming");Folder director2 = new Folder("xiaolinzhengshu");// 四級目錄File movieFile1 = new File("luoshengmen.mp4");File movieFile2 = new File("qiwushi.mp4");director1.add(movieFile1);director1.add(movieFile2);File movieFile3 = new File("duomingjian.mp4");File movieFile4 = new File("qiefu.mp4");director2.add(movieFile3);director2.add(movieFile4);movies.add(director1);movies.add(director2);// 文件夾添加到頂級文件夾folder.add(images);folder.add(movies);folder.show();}
}

執行如下,也實現了目的

在這里插入圖片描述

這么看下來,文件系統場景使用組合模式實現是很不錯的,代碼少了很多,也削減了文件夾類中的職責(可以對比下Folder類前后的代碼)

使用場景

在《設計模式就該這樣學》(P229)這本書中,提到狀態模式適用于以下場景:

(1)希望客戶端可以忽略組合對象與單個對象的差異;

(2)對象層次具備整體和部分,呈樹形結構;

除了文件系統、企業組織架構場景,我還沒想到其他使用場景;

總結

本文介紹了結構型設計模式中的組合模式,參考《設計模式就該這樣學》、《秒懂設計模式》、《設計模式的藝術》(第一版)這三本書,其中的例子來自《秒懂設計模式》。

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

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

相關文章

【TMS570LC4357】之相關驅動開發學習記錄2

系列文章目錄 【TMS570LC4357】之工程創建 【TMS570LC4357】之工程配置修改 【TMS570LC4357】之HALCOGEN使用 【TMS570LC4357】之相關問題及解決 【TMS570LC4357】之相關驅動開發學習記錄1 ——————————————————— 前言 記錄筆者在第一次使用TMS570過程中對…

3D Gaussian splatting 05: 代碼閱讀-訓練整體流程

目錄 3D Gaussian splatting 01: 環境搭建3D Gaussian splatting 02: 快速評估3D Gaussian splatting 03: 用戶數據訓練和結果查看3D Gaussian splatting 04: 代碼閱讀-提取相機位姿和稀疏點云3D Gaussian splatting 05: 代碼閱讀-訓練整體流程3D Gaussian splatting 06: 代碼…

【黑馬程序員uniapp】項目配置、請求函數封裝

黑馬程序員前端項目uniapp小兔鮮兒微信小程序項目視頻教程&#xff0c;基于Vue3TsPiniauni-app的最新組合技術棧開發的電商業務全流程_嗶哩嗶哩_bilibili 參考 有代碼&#xff0c;還有app、h5頁面、小程序的演示 小兔鮮兒-vue3ts-uniapp-一套代碼多端部署: 小兔鮮兒-vue3ts-un…

前端使用 preview 插件預覽docx文件

目錄 前言一 引入插件二 JS 處理 前言 前端使用 preview 插件預覽docx文件 一 引入插件 建議下載至本地&#xff0c;靜態引入&#xff0c;核心的文件已打包&#xff08;前端使用 preview 插件預覽docx文件&#xff09;&#xff0c;在文章目錄處下載至本地&#xff0c;復制在項…

如何在運動中保護好半月板?

文章目錄 引言I 半月板的作用穩定作用緩沖作用潤滑作用II 在跳繩運動中保護好半月板III 半月板損傷自測IV 半月板“殺手”半月板損傷必須滿足四個因素:消耗品引言 膝蓋是連接大腿骨和小腿骨的地方,在兩部分骨頭的連接處,墊著兩片半月形的纖維軟骨板,這就是半月板。半月板分…

安科瑞防逆流方案落地內蒙古中高綠能光伏項目,筑牢北疆綠電安全防線

一、項目概況 內蒙古阿拉善中高綠能能源分布式光伏項目&#xff0c;位于內蒙古烏斯太鎮&#xff0c;裝機容量為7MW&#xff0c;采用自發自用、余電不上網模式。 用戶配電站為35kV用戶站&#xff0c;采用兩路電源單母線分段系統。本項目共設置12臺35/0.4kV變壓器&#xff0c;在…

1.3 fs模塊詳解

fs 模塊詳解 Node.js 的 fs 模塊提供了與文件系統交互的能力&#xff0c;是服務器端編程的核心模塊之一。它支持同步、異步&#xff08;回調式&#xff09;和 Promise 三種 API 風格&#xff0c;可滿足不同場景的需求。 1. 模塊引入 const fs require(fs); // 回調…

LeetCode 70 爬樓梯(Java)

爬樓梯問題&#xff1a;動態規劃與斐波那契的巧妙結合 問題描述 假設你正在爬樓梯&#xff0c;需要爬 n 階才能到達樓頂。每次你可以爬 1 或 2 個臺階。求有多少種不同的方法可以爬到樓頂&#xff1f; 示例&#xff1a; n 2 → 輸出 2&#xff08;1階1階 或 2階&#xff0…

【學習分享】shell基礎-參數傳遞

參數傳遞 我們可以在執行 Shell 腳本時&#xff0c;向腳本傳遞參數&#xff0c;腳本內獲取參數的格式為 $n&#xff0c;n 代表一個數字&#xff0c;1 為執行腳本的第一個參數&#xff0c;2 為執行腳本的第二個參數。 例如可以使用 $1、$2 等來引用傳遞給腳本的參數&#xff0…

Fluence推出“Pointless計劃”:五種方式參與RWA算力資產新時代

2025年6月1日&#xff0c;去中心化算力平臺 Fluence 正式宣布啟動“Pointless 計劃”——這是其《Fluence Vision 2026》戰略中四項核心舉措之一&#xff0c;旨在通過貢獻驅動的積分體系&#xff0c;激勵更廣泛的社區參與&#xff0c;為用戶帶來現實世界資產&#xff08;RWA&am…

Excel數據分析:基礎

在現代辦公環境中&#xff0c;Excel 是一款不可或缺的工具&#xff0c;它是 Microsoft&#xff08;微軟&#xff09;開發的電子表格軟件&#xff0c;用于處理和分析結構化數據。市場上還有其他類似的軟件&#xff0c;如 Google Sheets 和 Apple Numbers&#xff0c;但 Excel 以…

12V降5V12A大功率WD5030A,充電器、便攜式設備、網絡及工業領域的理想選擇

WD5030A 高效單片同步降壓型直流 / 直流轉換器 一、芯片核心概述 WD5030A 是一款高性能同步降壓型 DC/DC 轉換器&#xff0c;采用 平均電流模式控制架構&#xff08;帶頻率抖動功能&#xff09;&#xff0c;具備以下核心優勢&#xff1a; 精準電流控制&#xff1a;快速響應負…

企業級AI邁入黃金時代,企業該如何向AI“蝶變”?

科技云報到原創。 近日&#xff0c;微軟&#xff08;MSFT.US&#xff09;在最新全員大會上高調展示企業級AI業務進展&#xff0c;其中與巴克萊銀行達成的10萬份Copilot許可證交易成為焦點。 微軟首席商務官賈德森阿爾索夫在會上披露&#xff0c;這家英國金融巨頭已簽約采購相…

Java編程課(一)

Java編程課 一、java簡介二、Java基礎語法2.1 環境搭建2.2 使用Intellij IDEA新建java項目2.3 Java運行介紹2.4 參數說明2.5 Java基礎語法2.6 注釋2.7 變量和常量一、java簡介 Java是一種廣泛使用的高級編程語言,最初由Sun Microsystems于1995年發布。它被設計為具有簡單、可…

【Java Web】速通Tomcat

參考筆記:JavaWeb 速通Tomcat_tomcat部署java項目-CSDN博客 目錄 一、Tomcat服務 1. 下載和安裝 2. 啟動Tomcat服務 3. 啟動Tomcat服務的注意事項 4. 關閉Tomcat服務 二、Tomcat的目錄結構 1. bin ?? 2. conf ?? 3. lib 4. logs 5. temp 6. webapps 7. work 三、Web項目…

Mysql 身份認證繞過漏洞 CVE-2012-2122

前言&#xff1a;CVE-2012-2122 是一個影響 MySQL 和 MariaDB 的身份驗證漏洞&#xff0c;存在于特定版本中 vulhub/mysql/CVE-2012-2122/README.zh-cn.md at master vulhub/vulhubhttps://github.com/vulhub/vulhub/blob/master/mysql/CVE-2012-2122/README.zh-cn.md 任務一…

Win10停更,Win11不好用?現在Mac電腦比Win11電腦更便宜

最近不少朋友在換電腦前都犯了難。 以前大家最常說的一句是&#xff1a;“Mac太貴了&#xff0c;還是買Windows吧。”但現在不一樣了&#xff0c;國補教育優惠下來&#xff0c;新款M4芯片的Mac mini的入門價已經降到了3000元左右&#xff0c;曾經的價格壁壘&#xff0c;已經不…

C#中Struct與IntPtr轉換:實用擴展方法

C#中Struct與IntPtr轉換&#xff1a;實用擴展方法 在 C# 編程的世界里&#xff0c;我們常常會遇到需要與非托管代碼交互&#xff0c;或者進行一些底層內存操作的場景。這時&#xff0c;IntPtr類型就顯得尤為重要&#xff0c;它可以表示一個指針或句柄&#xff0c;用來指向非托…

手機歸屬地查詢接口如何用Java調用?

一、什么是手機歸屬地查詢接口&#xff1f; 是一種便捷、高效的工具&#xff0c;操作簡單&#xff0c;請求速度快。它不僅能夠提高用戶填寫地址的效率&#xff0c;還能幫助企業更好地了解客戶需求&#xff0c;制定個性化的營銷策略&#xff0c;降低風險。隨著移動互聯網的發展…

43、視圖解析-Thymeleaf初體驗

43、視圖解析-Thymeleaf初體驗 “43、視圖解析-Thymeleaf初體驗”通常是指在學習Spring Boot框架時&#xff0c;關于如何使用Thymeleaf模板引擎進行視圖解析的入門課程或章節。以下是對該主題的詳細介紹&#xff1a; #### Thymeleaf簡介 - **定義**&#xff1a;Thymeleaf是一個…