设计模式(十一):从文Finder中认识组合模式(Composite Pattern)
上一篇博客中我們從從電影院中認識了"迭代器模式"(Iterator Pattern),今天我們就從文件系統中來認識一下“組合模式”(Composite Pattern)。說到組合模式,在此我想聊一下在類圖中有組合與聚合的關系,這兩者都是整體和部分的關系,只是整體與部分的依賴度不同。在聚合關系中,整體強烈依賴于部分,而部分脫離于整體將沒有存在的意義,比如你身上的器官與你的關系就是聚合關系。而對于組合關系來說整體與部分的依賴就相對于小一些,離開彼此也是可以獨立生存的,比如員工與公司的關系,就是組合關系。
言歸正傳,今天我們來介紹一下“組合模式”。下方就是組合模式的定義:
組合模式:允許你將對象組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象已經對象組合
組合模式也就是將多個獨立的個體組合到一塊,不過組合時是有層級關系的,而這些層級關系是“樹”形的關系。典型的樹狀層級關系就是我們的文件系統,下方截圖就是我們資源管理器的一個文件層級的截圖。可以明確的看出下方是樹狀的層級關系。今天我們的任務就是使用“組合模式”模擬下方的文件結構。從下方的截圖中我們可以分析出文件總體上可以分為兩種類型,一個是文件夾,在一個就是真正有內容的文件。文件夾是一種容器,它不僅可以存儲文件還可以存儲文件夾。文件夾可以存儲文件以及其他文件夾,這一特性就決定文件系統是一個樹形結構。
? ? ? ?
?
一、模擬“文件系統”實現的類圖設計
依舊是老套路,我們要使用代碼結合“組合模式”來模仿上面截圖中的文件結構,首先我們先來設計類圖,然后在根據我們設計的類圖來給出代碼實現。上面我們已經提到過文件夾就是可以存儲其他文件夾和文件的容器,所以在我們設計實現是打算使用Dictionary(字典)來實現這一容器的特性,至于如何去實現下方會給出具體的實現方式。下方的類圖就是我們要實現的“文件系統”的類圖,當然我們是模擬的,盡量的簡化了一些操作。下方也使用了組合模式,Folder類就是組合文件夾與文件的地方,稍后會給出具體的說明。
首先我們來介紹下方黃色框中的文件類型協議與該協議的延展。FileType是我們所有文件的協議,無論是文件夾還是具體文件都遵循該協議,該協議中給出了文件以及文件夾的必要操作。在該協議的默認延展中給出了協議中那些只需要文件夾實現而具體文件不需要實現的方法,如addFile()、deleteFile()方法,只有文件夾容器才會有這些方法。該協議的具體呢絨如下類圖中黃框中的內容所示。
然后是紅框中的部分,紅框中是我們文件夾的實現,也是我們組合模式的核心模塊。經過觀察Folder(文件夾)類,我們不難發現Folder不僅僅遵循了FileType接口,還依賴于FileType接口。因為Folder是文件的一種類型,所以要遵循FileType接口。同時Folder是文件的容器,可以存放所有的文件和文件夾(也就是遵循FileType接口的所有類),所以Folder依賴于FileType接口。這個特性決定了組合模式有著樹形結構。
最后是綠框中的部分,該部分的代碼比較單純。綠框中是具體文件的類。該模塊有一個基類,也就是BaseFile。所有的具體文件都繼承自BaseFile,因為BaseFile也是文件的一種所以也需要遵循FileType協議。因為具體文件不是容器,不需要實現addFile()等容器使用到的方法。因為具體文件遵循了FileType協議,而Folder依賴于FileType協議,所以Folder可以存儲具體文件。整體的類圖如下所示:
?
?
?
二、“文件系統”的代碼實現
有了上面的類圖,再給出相應的代碼實現就容易的多了。接下來我們就根據上面的類圖,給出相應的Swift代碼實現。首先我們會給出FileType協議以及其延展的實現,具體代碼片段如下所示。getFileName()方法用戶獲取文件名,addFile(file)用于文件夾添加文件,deleteFile(file)用于文件夾刪除文件,display()用于打印文件名。FileType延展中給出了具體文件不需要實現的方法,所以在延展中給出了一個默認的實現,類似于抽象類中的方法實現。因為在協議延展中給出了方法的默認實現,所以在文件類中的可以不給出協議延展中的方法。FileType與其延展的代碼段如下所示。
? ??
?
實現完相關的接口和擴展后就開始實現我們的具體類了,接下來我們將要給出組合模式的核心類Folder(容器類)。下方的Folder就是我們用代碼實現的文件夾,Folder遵循了FileType接口,并給出了相應方法的具體實現。在Folder中我們要注意一下files屬性,該屬性就是組合的聚集地。我們可以看出files的類型是一個字典,字典的key是String類型,而字典的Value是FileType類型。也就是說files中可以存儲遵循FileType協議的所有類,也就是files中可以存儲文件和文件夾。“組合模式”在此處的提現就是文件以及文件夾在一塊進行組合會生成一個新的文件夾。
下方還需要注意的就是Folder中的display()方法。該方法是遍歷files數組,然后取出其中的文件或者文件夾對象,然后調用這些對象的display()方法。這樣就會輸出當前文件夾下所有的文件的名稱。Folder文件夾類的具體實現方式如下所示:
? ?
?
上面給出了文件夾的實現,接著我們要實現另一種文件類型,就是具體的文件了。在實現具體文件時,我們定義了一個具體文件的基類,就是BaseFile。當然BaseFile也遵循與FileType協議,這就是我們面向接口編程。在BaseFile基類中我們給出了所有文件所共有的方法,比如getFileName()和display()方法。接著我們又實現了兩個特定的文件類型,一個Swift源文件SwiftFile,另一個就是Objective-C源文件ObjCFile。這兩個具體的文件都繼承自BaseFile類。具體代碼實現如下所示:
? ??
?
三、測試用例
接下來就到了測試用例的部分了,也就是上面類圖中的Client的部分。Client就是該文件系統的使用者,從類圖中我們可以看出來,Client依賴于FileType接口而不依賴于具體實現。因為我們是在Xcode中的Playground中做的測試,所以我們就沒有給出具體的Client類。但是下方代碼就等同于Client類中的代碼。下方就是我們的測試用例我們構建了本文開頭的文件目錄結構,并輸出了文件夾下所有文件的名稱。測試用例與輸出結果如下所示:
? ??
至此我們的“組合模式”的一個完整示例就執行完了。
同樣今天的Demo也會在github上進行分享,分享地址為:https://github.com/lizelu/DesignPatterns-Swift
?
轉載于:https://www.cnblogs.com/ludashi/p/5439128.html
總結
以上是生活随笔為你收集整理的设计模式(十一):从文Finder中认识组合模式(Composite Pattern)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常用快捷键归纳
- 下一篇: JavaMail中附件名称有乱码