設計模式之組合模式(Composite 模式)

引入composite模式
在計算機文件系統中,有文件夾的概念,文件夾里面既可以放入文件也可以放入文件夾,但是文件中卻不能放入任何東西。文件夾和文件構成了一種遞歸結構和容器結構。
雖然文件夾和文件是不同的對象,但是他們都可以被放入到文件夾里,所以一定意義上,文件夾和文件又可以看作是同一種類型的對象,所以我們可以把文件夾和文件統稱為目錄條目,(directory entry).在這個視角下,文件和文件夾是同一種對象。
所以,我們可以將文件夾和文件都看作是目錄的條目,將容器和內容作為同一種東西看待,可以方便我們遞歸的處理問題,在容器中既可以放入容器,又可以放入內容,然后在小容器中,又可以繼續放入容器和內容,這樣就構成了容器結構和遞歸結構。
這就引出了我們本文所要討論的composite模式,也就是組合模式,組合模式就是用于創造出這樣的容器結構的。是容器和內容具有一致性,可以進行遞歸操作。

composite模式的具體實例
我們實現一個實例程序,可以列出文件和文件夾的信息。
自然,根據前文的討論,我們需要建立三個類,一個文件類,一個文件夾類,同時還要抽象出兩種類的共性,新建一個entry類,也就是目錄條目類,這個類是實現文件類和文件夾類的一致性的。

我們先簡單看一下類圖:

在這里插入圖片描述
首先我們實現Entry類,這個類表示目錄條目的抽象類

package Composite;public abstract class Entry {public abstract String getName();public abstract int getSize();public Entry add(Entry entry) throws FileTreatMentException {throw new FileTreatMentException();}public void printList() {printList("");}protected abstract void printList(String prefix);public String toString() {return getName() + "(" + getSize() + ")";}
}

File類是文件類

package Composite;public class File extends Entry {private String name;private int size;public File(String name, int size) {this.name = name;this.size = size;}@Overridepublic String getName() {return name;}@Overridepublic int getSize() {return size;}@Overrideprotected void printList(String prefix) {System.out.println(prefix + '/' + this);}}

Directory是目錄類,它持有一個目錄的集合

package Composite;import java.util.ArrayList;
import java.util.Iterator;public class Directory extends Entry {private String name;private ArrayList directory = new ArrayList();public Directory(String name) {this.name = name;}@Overridepublic String getName() {return name;}@Overridepublic int getSize() {int size = 0;Iterator it = directory.iterator();while(it.hasNext()) {Entry entry = (Entry)it.next();size += entry.getSize();}return size;}public Entry add(Entry entry) {directory.add(entry);return this;}@Overrideprotected void printList(String prefix) {System.out.println(prefix + "/" + this);Iterator it = directory.iterator();while(it.hasNext()) {Entry entry = (Entry)it.next();entry.printList(prefix + "/" + name);}}}

我們新建一個測試類

package Composite;public class Main {public static void main(String[] args) {try {System.out.println("Making root entries...");Directory rootdir = new Directory("root");Directory bindir = new Directory("bin");Directory tmpdir = new Directory("tmp");Directory usrdir = new Directory("usr");rootdir.add(bindir);rootdir.add(tmpdir);rootdir.add(usrdir);bindir.add(new File("vi", 10000));bindir.add(new File("latex", 20000));rootdir.printList();System.out.println("");System.out.println("Making user entries...");Directory yuki = new Directory("yuki");Directory hanako = new Directory("hanako");Directory tomura = new Directory("tomura");usrdir.add(yuki);usrdir.add(hanako);usrdir.add(tomura);yuki.add(new File("diary.html", 100));yuki.add(new File("Composite.java", 200));hanako.add(new File("memo.tex", 300));tomura.add(new File("game.doc", 400));tomura.add(new File("junk.mail", 500));rootdir.printList();} catch (FileTreatMentException e) {e.printStackTrace();}}}

輸出結果:
在這里插入圖片描述
composite模式
composite模式主要有一下幾類角色

leaf 樹葉
表示內容的角色,該角色中不能放入其他對象,對應我們實例程序中的file

Composite 復合物
表示容器的角色,可以放入小容器和內容,也就是leaf和composite,此實例中,由directory類代表composite

component
是leaf和composite角色具有一致性的角色,一般作為leaf和composite的父類,定義一些共有的行為和屬性,此例中的entry類代表

類圖如下:

在這里插入圖片描述
典型的composite結構:
在這里插入圖片描述
一個小問題,add方法應該放在哪里?
因為add方法只是容器可以使用的,內容無法使用add,所以add方法的位置可以有所選擇,我們實例中是將add放在entry中,同時拋出異常,當文件類調用的時候就拋出異常

定義在entry類中,報錯
就是我們實例中的做法,讓其報錯

定義在entr類,但什么都不做
交給要做的子類去做

聲明在entry中,但不實現
子類需要實現,優點是所有子類都要實現add,但是file本不需要add,卻也要實現

只定義在directory中
就是在使用的時候需要進行類型轉換。

小結
在實例程序中,我們以文件夾的結構實現了composite模式,實際上現實世界中,到處都存在composite模式,例如,視窗系統中,窗口可以含有子窗口也可以含有button類似的控件。通常來說,樹結構的數據結構都適合composite模式

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

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

相關文章

Ansible批量在遠程主機執行命令

Ansible直接執行遠程命令,不用ssh登陸交互執行。    如下:    ansible all -i 192.168.199.180, -m shell -a "ifconfig" -u supermap    參數解釋:    -i 連接到遠程主機“192.168.199.180,”&#xf…

HOJ 2651

一道二分的題目&#xff0c;但要注意不能用double&#xff0c; 并且要注意一下二分的步驟 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define pi 3.1415926535898 #define eps 0.0001 using namespace std; inl…

HierarchicalBeanFactory接口

HierarchicalBeanFactory 提供父容器的訪問功能.至于父容器的設置,需要找ConfigurableBeanFactory的setParentBeanFactory(接口把設置跟獲取給拆開了!). HierarchicalBeanFactory源碼具體&#xff1a; 1、第一個方法返回本Bean工廠的父工廠。這個方法實現了工廠的分層。 2、第…

C++: C++函數聲明的時候后面加const

C: C函數聲明的時候后面加const 轉自&#xff1a;http://blog.csdn.net/zhangss415/article/details/7998123 非靜態成員函數后面加const&#xff08;加到非成員函數或靜態成員后面會產生編譯錯誤&#xff09;&#xff0c;表示成員函數隱含傳入的this指針為const指針&#xff0…

【計蒜客習題】消除字符串

問題描述 蒜頭君喜歡中心對稱的字符串&#xff0c;即回文字符串。現在蒜頭君手里有一個字符串 SS&#xff0c;蒜頭君每次都會進行這樣的操作&#xff1a;從 SS 中挑選一個回文的子序列&#xff0c;將其從字符串 SS 中去除&#xff0c;剩下的字符重組成新的字符串 SS。 蒜頭君想…

HierarchicalBeanFactory

BeanFactory分層 package org.springframework.beans.factory;//分層工廠 public interface HierarchicalBeanFactory extends BeanFactory {//返回工廠的父工廠BeanFactory getParentBeanFactory();//這個工廠中是否包含這個Beanboolean containsLocalBean(String name); }測…

Training a classifier

你已經學習了如何定義神經網絡&#xff0c;計算損失和執行網絡權重的更新。 現在你或許在思考。 What about data? 通常當你需要處理圖像&#xff0c;文本&#xff0c;音頻&#xff0c;視頻數據&#xff0c;你能夠使用標準的python包將數據加載進numpy數組。之后你能夠轉換這些…

19歲白帽子通過bug懸賞賺到一百萬美元--轉

出處&#xff1a;https://news.cnblogs.com/n/620858/ 19 歲的 Santiago Lopez 通過 bug 懸賞平臺 HackerOne 報告漏洞&#xff0c;成為第一位通過 bug 懸賞賺到一百萬美元的白帽子黑客。他的白帽子生涯始于 2015 年&#xff0c;至今共報告了超過 1600 個安全漏洞。他在 16 歲時…

代碼分層的設計

分層思想&#xff0c;是應用系統最常見的一種架構模式&#xff0c;我們會將系統橫向切割&#xff0c;根據業務職責劃分。MVC 三層架構就是非常典型架構模式&#xff0c;劃分的目的是規劃軟件系統的邏輯結構便于開發維護。MVC&#xff1a;英文即 Model-View-Controller&#xff…

【24小時內第四更】為什么我們要堅持寫博客?

前言 從2018年7月份&#xff0c;我開始了寫作博客之路。開始之前&#xff0c;我打算分享下之前的經歷。去年初公司來了個架構師&#xff0c;內部分享過docker原理&#xff0c;TDD單元測試驅動&#xff0c;并發并行異步編程等內容&#xff0c;讓我著實驚呆了&#xff0c;因為確實…

sqoop快速入門

轉自http://www.aboutyun.com/thread-22549-1-1.html 轉載于:https://www.cnblogs.com/drjava/p/10473297.html

ListableBeanFactory接口

ListableBeanFactory獲取bean時,Spring 鼓勵使用這個接口定義的api. 還有個Beanfactory方便使用.其他的4個接口都是不鼓勵使用的. 提供容器中bean迭代的功能,不再需要一個個bean地查找.比如可以一次獲取全部的bean(太暴力了),根據類型獲取bean.在看SpringMVC時,掃描包路徑下的…

HDU 4035 Maze

Maze http://acm.hdu.edu.cn/showproblem.php?pid4035 分析&#xff1a; 在樹上走來走去&#xff0c;然后在一個點可以k的概率回到1&#xff0c;可以e的概率走出去&#xff0c;可以1-k-e的概率走到其他的位置&#xff08;分為父節點和子節點討論&#xff09;。 轉移方程就是&a…

面向對象之三大特性:繼承,封裝,多態

python面向對象的三大特性&#xff1a;繼承&#xff0c;封裝&#xff0c;多態。 1. 封裝: 把很多數據封裝到?個對象中. 把固定功能的代碼封裝到?個代碼塊, 函數, 對象, 打包成模塊. 這都屬于封裝的思想. 具體的情況具體分析. 比如. 你寫了?個很?B的函數. 那這個也可以被稱為…

configurablebeanfactory

ConfigurableBeanFactory定義BeanFactory的配置.ConfigurableBeanFactory中定義了太多太多的api,比如類加載器,類型轉化,屬性編輯器,BeanPostProcessor,作用域,bean定義,處理bean依賴關系,合并其他ConfigurableBeanFactory,bean如何銷毀. ConfigurableBeanFactory同時繼承了Hi…

Xlua文件在熱更新中調用方法

Xlua文件在熱更新中調用方法 public class news : MonoBehaviour { LuaEnv luaEnv;//定義Lua初始變量 void Awake() { luaEnv new LuaEnv();//new開辟空間 luaEnv.AddLoader(myload);//調用方法地址、返回字節 luaEnv.DoString("requirefish");//更新文件 } void O…

springboot 使用的配置

1&#xff0c;控制臺打印sql logging:level:com.sdyy.test.mapper: debug 2&#xff0c;開啟駝峰命名 mybatis.configuration.map-underscore-to-camel-casetrue 轉載于:https://www.cnblogs.com/xiaohu1218/p/10477318.html

AutowireCapableBeanFactory接口

AutowireCapableBeanFactory在BeanFactory基礎上實現了對存在實例的管理.可以使用這個接口集成其它框架,捆綁并填充并不由Spring管理生命周期并已存在的實例.像集成WebWork的Actions 和Tapestry Page就很實用. 一般應用開發者不會使用這個接口,所以像ApplicationContext這樣的…

外觀模式

一、什么是外觀模式   有些人可能炒過股票&#xff0c;但其實大部分人都不太懂&#xff0c;這種沒有足夠了解證券知識的情況下做股票是很容易虧錢的&#xff0c;剛開始炒股肯定都會想&#xff0c;如果有個懂行的幫幫手就好&#xff0c;其實基金就是個好幫手&#xff0c;支付寶…

OC內存管理

OC內存管理 一、基本原理 &#xff08;一&#xff09;為什么要進行內存管理。 由于移動設備的內存極其有限&#xff0c;所以每個APP所占的內存也是有限制的&#xff0c;當app所占用的內存較多時&#xff0c;系統就會發出內存警告&#xff0c;這時需要回收一些不需要再繼續使用的…