Java設(shè)計(jì)模式:組合模式
在本講,我們來學(xué)習(xí)一下結(jié)構(gòu)型模式里面的第六個(gè)設(shè)計(jì)模式,即組合模式。
概述
在學(xué)習(xí)組合模式之前,我們先來看下面這張圖。
對于以上這張圖大家應(yīng)該很熟悉,我們可以將其看作是一個(gè)文件系統(tǒng),其實(shí)說到底它就是Windows系統(tǒng)里面的一個(gè)目錄結(jié)構(gòu),只不過對于Windows中的文件系統(tǒng)而言,它里面包含有C盤、D盤、E盤等等盤符,而這里我們只是以它里面的某一個(gè)盤符里面的目錄結(jié)構(gòu)為例來進(jìn)行了一個(gè)描述。
對于這樣的結(jié)構(gòu)我們稱之為樹形結(jié)構(gòu)。為啥叫樹形結(jié)構(gòu)呢?你看一下上圖中的左邊部分,最上面是不是有一個(gè)WINDOWS目錄啊,而該WINDOWS目錄下面又有很多的子目錄或者子文件,這樣,我們就能將其描述成上圖右邊部分的樹形結(jié)構(gòu)了,它是不是很像一棵倒著的樹啊!既然是一棵樹,那么它就只有一個(gè)樹根了,很明顯,這個(gè)樹根就是最頂層的WINDOWS目錄,在該目錄下,自然就會生成許多的子文件或者子文件夾了,而如果要是子文件夾的話,那么它下面又可以有許多的子文件或者子文件夾了,以此類推,一棵參天大樹就長成了。
對于這樣一個(gè)文件系統(tǒng)而言,有幾個(gè)概念大家需要知道一下,文件夾或者文件我們都可稱之為節(jié)點(diǎn),但是一般來說,我們稱文件為葉子節(jié)點(diǎn),稱文件夾為樹枝節(jié)點(diǎn),這是因?yàn)闃渲€可以再去生成子樹枝或者子葉子。
在這樣一個(gè)樹形結(jié)構(gòu)中,我們可以通過調(diào)用某個(gè)方法來遍歷整棵樹,當(dāng)我們找到某個(gè)葉子節(jié)點(diǎn)后,就可以對葉子節(jié)點(diǎn)進(jìn)行相關(guān)的操作了。因此,我們不妨將這顆樹理解成一個(gè)大的容器,容器里面包含有很多的成員對象(其實(shí)就是節(jié)點(diǎn)對象),這些成員對象既可以是容器對象(即文件夾,當(dāng)然你也可以把它稱作是樹枝對象)也可以是葉子對象(即文件)。但是由于容器對象和葉子對象在功能上面有所區(qū)別(區(qū)別是很明顯的,葉子對象,即文件,可以讀寫數(shù)據(jù),但是它下面不可能再有子文件或者子文件夾了;而容器對象,即文件夾,它下面是可以再有子文件或者子文件的,但是它不能進(jìn)行數(shù)據(jù)的一個(gè)讀寫操作),使得我們在使用的過程中必須要區(qū)分容器對象和葉子對象,但是這樣一來就會給客戶帶來不必要的麻煩,對于客戶來說的話,他始終是希望能夠一致的對待容器對象和葉子對象。也就是說,對于客戶而言,不管是文件夾還是文件,他都希望一致的去對待它們,即把它們都當(dāng)作同樣的一個(gè)對象來進(jìn)行處理。
至此,我們就認(rèn)識了一下以上樹形結(jié)構(gòu),并且咱們還知道了該樹形結(jié)構(gòu)所存在的一個(gè)問題。那如何解決該問題呢?很明顯,就要用到組合模式了,因?yàn)楸疚闹v的就是組合模式嘛!
那什么是組合模式呢?下面我們來看看它的概念。
組合模式又名部分整體模式(啥又叫部分整體模式呢?上面不是說過嘛,我們可以將一棵樹理解成一個(gè)大的容器,對于該容器而言,它就是整體;然后它下面不是又有子文件或者子文件夾嘛,這些子文件或者子文件夾我們就稱之為部分,當(dāng)然,部分下面是不是還可以再分出部分來啊?。?,是用于把一組相似的對象當(dāng)作一個(gè)單一的對象。組合模式依據(jù)樹形結(jié)構(gòu)來組合對象,用來表示部分以及整體層次,這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它創(chuàng)建了對象組的樹形結(jié)構(gòu)。
看完以上組合模式的概念之后,相信大家就能知道應(yīng)該要使用組合模式來解決以上樹形結(jié)構(gòu)所存在的問題了,因?yàn)閷τ诳蛻舳?,他就能一致的去對待容器對象和葉子對象了,這樣,他使用起來也會變得更加簡單。
結(jié)構(gòu)
組合模式主要包含有三種角色:
- 抽象根節(jié)點(diǎn)(Component):定義系統(tǒng)各層次對象具有的共有方法和屬性,可以預(yù)先定義一些默認(rèn)行為和屬性。
怎么來理解抽象根節(jié)點(diǎn)呢?還是通過上圖來理解,不管是文件夾還是文件,我們都可以向上抽取,抽取出一個(gè)抽象類,而在這個(gè)抽象類里面,我們就可以去定義文件和文件夾中的共有行為和屬性了。也就是說,正是因?yàn)榭蛻羲胍恢碌娜Υ萜鲗ο蠛腿~子對象,所以他就可以定義出這么一個(gè)公共的抽象類了
- 樹枝節(jié)點(diǎn)(Composite):定義樹枝節(jié)點(diǎn)的行為,即存儲子節(jié)點(diǎn),組合樹枝節(jié)點(diǎn)和葉子節(jié)點(diǎn)形成一個(gè)樹形結(jié)構(gòu)。
- 葉子節(jié)點(diǎn)(Leaf):葉子節(jié)點(diǎn)對象,其下再無分支,是系統(tǒng)層次遍歷的最小單位。
組合模式案例
接下來,我們就通過一個(gè)案例再來理解一下組合模式,這個(gè)案例就是軟件菜單。
分析
先來看一下下面這張圖。
相信大家還是比較熟悉以上這張圖的,因?yàn)槲覀冊谠L問別的一些管理系統(tǒng)時(shí),經(jīng)??梢钥吹筋愃频牟藛?。一個(gè)菜單可以包含菜單項(xiàng)(菜單項(xiàng)是指不再包含其他內(nèi)容的菜單條目),也可以包含帶有其他菜單項(xiàng)的菜單,就拿以上系統(tǒng)管理菜單來說,它下面有三個(gè)子菜單,分別是菜單管理、權(quán)限配置、角色管理,它們都是屬于菜單,因?yàn)樗鼈兿旅孢€可以有子菜單或者子菜單項(xiàng)。對于菜單管理來說,它下面有五個(gè)子菜單項(xiàng),分別是頁面訪問、展開菜單、編輯菜單、刪除菜單、新增菜單,注意了,它們都是菜單項(xiàng),下面不可能再有子菜單或者子菜單項(xiàng)了,故它們都是屬于葉子節(jié)點(diǎn);而系統(tǒng)管理、菜單管理、權(quán)限配置、角色管理,它們均屬于樹枝節(jié)點(diǎn),并且系統(tǒng)管理從根本上來說,它是屬于根節(jié)點(diǎn)。因此,使用組合模式來描述以上菜單就很恰當(dāng)了。
這樣,我們的需求就是針對一個(gè)菜單,例如系統(tǒng)管理,打印出其包含的所有菜單以及菜單項(xiàng)的名稱。
需求明確之后,接下來我們就要編寫代碼解決該需求了。首先,對于該需求,我們先設(shè)計(jì)出一個(gè)如下的類圖。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
springboot升級到j(luò)dk21最新教程(2023年)
你還在使用jdk8?快來看看最新出爐的SpringBoot+jdk21如何使用,下面這篇文章主要給大家介紹了關(guān)于springboot升級到j(luò)dk21的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10Spring中的EventListenerMethodProcessor組件詳解
這篇文章主要介紹了Spring中的EventListenerMethodProcessor組件詳解,EventListenerMethodProcessor 是 Spring 事件機(jī)制中非常重要的一個(gè)組件,它管理了一組EventListenerFactory組件,用來將應(yīng)用中每個(gè)使用@EventListener注解定義的事件監(jiān)聽,需要的朋友可以參考下2023-12-12springboot使用hibernate validation對參數(shù)校驗(yàn)的實(shí)現(xiàn)方法
這篇文章主要介紹了spring-boot 使用hibernate validation對參數(shù)進(jìn)行優(yōu)雅的校驗(yàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12Mybatis基于注解形式的sql語句生成實(shí)例代碼
這篇文章主要介紹了 Mybatis基于注解形式的sql語句生成實(shí)例代碼,需要的朋友可以參考下2017-09-09通過Java?Reflection實(shí)現(xiàn)編譯時(shí)注解正確處理方法
Java注解是一種標(biāo)記在JDK5及以后的版本中引入,用于Java語言中向程序添加元數(shù)據(jù)的方法,這篇文章主要介紹了通過Java?Reflection實(shí)現(xiàn)編譯時(shí)注解處理方法,需要的朋友可以參考下2023-06-06Java中的FileInputStream是否需要close問題
這篇文章主要介紹了Java中的FileInputStream是否需要close問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12Spring?Security中使用authorizeRequests遇到的問題小結(jié)
Spring?是非常流行和成功的?Java?應(yīng)用開發(fā)框架,Spring?Security?正是?Spring?家族中的成員,這篇文章主要介紹了Spring?Security中使用authorizeRequests遇到的問題,需要的朋友可以參考下2023-02-02