Go設計模式(16)-組合模式

組合模式針對於特定場景,如檔案管理、組織管理等,使用該模式能簡化管理,使程式碼變得非常簡潔。

UML類圖位置:https://www。processon。com/diagraming/609b375407912943913a4c13

本文程式碼連結為:https://github。com/shidawuhen/asap/blob/master/controller/design/16composite。go

1。定義

1。1組合模式

組合模式

:將物件組合成樹形結構以表示‘部分-整體’的層次結構。

組合模式使得使用者對單個物件和組合物件的使用具有一致性。

UML

Go設計模式(16)-組合模式

1。2分析

單看UML圖可能不清晰,舉個栗子會容易一些。Composite是目錄,Leaf是目錄下的檔案,目錄和檔案都繼承自Component。目錄能夠增加、刪除檔案,可以展示目錄所在位置,檔案只能展示檔案所在位置。

對於目錄這種需求,有兩種實現方式。

第一種不使用組合模式,只用一個類,有2個核心變數

一個成員變量表明物件

檔案還是目錄

一個成員變數存放目錄下檔案列表,如果物件為檔案,則該變數為空

type FileSystemNode struct { isFile bool //表明是檔案還是目錄 subNodes []FileSystemNode //目錄下包含的內容}

第二種方案使用組合模式。雖然第一種方案能夠實現檔案管理的功能,但並不優雅。因為檔案和目錄是不同的,各自有各自的特性,將特有的內容放到一個類裡,

不滿足單一職責原則

所以我們可以將其拆分為兩個類:檔案類和目錄類。兩個類必須繼承自同一個父類,除了重複的功能可以複用外,更重要的一點是消除了兩個類呼叫上的區別,subNodes不需要做任何區分。而且這兩個類可以獨立進化,相互不影響,何樂而不為呢。

2。使用場景

組合模式在使用上,特別像深度優先遍歷或者廣度優先遍歷,一般用於組織結構、檔案管理上,這些功能都有共通點:個體和集體無論在功能上還是認知上都極為相似。

位元組跳動的協同辦公軟體-飛書,在文件管理部分,就極其適合使用組合模式,大家有時間可以嘗試一下,連結如下:https://www。feishu。cn/ ,其展現樣式如下所示:

Go設計模式(16)-組合模式

3。程式碼實現

這次程式碼簡單實現一下目錄和檔案的新增、顯示功能吧。

package mainimport “fmt”const Separator = “——”/** * @Author: Jason Pang * @Description: 檔案系統介面,檔案和目錄都要實現該介面 */type FileSystemNode interface { Display(separator string)}/** * @Author: Jason Pang * @Description: 檔案通用功能 */type FileCommonFunc struct { fileName string}/** * @Author: Jason Pang * @Description: 設定檔名稱 * @receiver f * @param fileName */func (f *FileCommonFunc) SetFileName(fileName string) { f。fileName = fileName}/** * @Author: Jason Pang * @Description: 檔案類 */type FileNode struct { FileCommonFunc}/** * @Author: Jason Pang * @Description: 檔案類顯示檔案內容 * @receiver f */func (f *FileNode) Display(separator string) { fmt。Println(separator + f。fileName + “ 檔案內容為:Hello,world”)}/** * @Author: Jason Pang * @Description: 目錄類 */type DirectoryNode struct { FileCommonFunc nodes []FileSystemNode}/** * @Author: Jason Pang * @Description: 目錄類展示檔名 * @receiver d */func (d *DirectoryNode) Display(separator string) { fmt。Println(separator + d。fileName) for _, node := range d。nodes { node。Display(separator + Separator) }}/** * @Author: Jason Pang * @Description: 新增目錄或者檔案 * @receiver d * @param f */func (d *DirectoryNode) Add(f FileSystemNode) { d。nodes = append(d。nodes, f)}func main() { //初始化 biji := DirectoryNode{} biji。SetFileName(“筆記”) huiyi := DirectoryNode{} huiyi。SetFileName(“會議”) chenhui := FileNode{} chenhui。SetFileName(“晨會。md”) zhouhui := FileNode{} zhouhui。SetFileName(“週會。md”) //組裝 biji。Add(&huiyi) huiyi。Add(&chenhui) huiyi。Add(&zhouhui) //顯示 biji。Display(Separator)}

顯示:

➜ myproject go run main。go

——筆記

——會議

————晨會。md 檔案內容為:Hello,world

————週會。md 檔案內容為:Hello,world

檔案類和目錄類都實現了FileSystemNode介面,所以目錄類管理檔案類如同管理自己一樣。兩者都組合了FileCommonFunc類,可以複用相同功能。最後就是兩者可以獨立變化,如目錄類有Add功能,但檔案類沒有。

3。總結

組合模式是對指定場景有用,所以大家能不能用到,完全看運氣。這個設計模式滿足單一職責原則、開閉原則、里氏替換原則。

最後

大家如果喜歡我的文章,可以關注我的公眾號(程式設計師麻辣燙)

我的個人部落格為:https://shidawuhen。github。io/

往期文章回顧:

招聘

位元組跳動|內推大放送

位元組跳動|今日頭條廣州服務端研發工程師內推

位元組跳動|抖音電商急招上海前端開發工程

位元組跳動|抖音電商上海資深服務端開發工程師-交易

位元組跳動|抖音電商武漢服務端(高階)開發工程師

位元組跳動|飛書大客戶產品經理內推咯

位元組跳動|抖音電商服務端技術崗位虛位以待

位元組跳動招聘專題

設計模式

Go設計模式(15)-門面模式

Go設計模式(14)-介面卡模式

Go設計模式(13)-裝飾器模式

Go設計模式(12)-橋接模式

Go設計模式(11)-代理模式

Go設計模式(10)-原型模式

Go設計模式(9)-建造者模式

Go設計模式(8)-抽象工廠

Go設計模式(7)-工廠模式

Go設計模式(6)-單例模式

Go設計模式(5)-類圖符號表示法

Go設計模式(4)-程式碼編寫最佳化

Go設計模式(4)-程式碼編寫

Go設計模式(3)-設計原則

Go設計模式(2)-面向物件分析與設計

Go設計模式(1)-語法

語言

再也不怕獲取不到Gin請求資料了

一文搞懂pprof

Go工具之generate

Go單例實現方案

Go通道實現原理

Go定時器實現原理

Beego框架使用

Golang原始碼BUG追查

Gin框架簡潔版

Gin原始碼剖析

架構

分頁複選設計的坑

支付接入常規問題

限流實現2

秒殺系統

分散式系統與一致性協議

微服務之服務框架和註冊中心

淺談微服務

限流實現1

CDN請求過程詳解

常用快取技巧

如何高效對接第三方支付

演算法總結

儲存

一文搞懂MySQL資料庫分庫分表

MySQL開發規範

Redis實現分散式鎖

事務原子性、一致性、永續性的實現原理

InnoDB鎖與事務簡析

網路

HTTP2。0基礎教程

HTTPS配置實戰

HTTPS連線過程

TCP效能最佳化

工具

GoLand實用技巧

根據mysql表自動生成go struct

Markdown編輯器推薦-typora

讀書筆記

《毛選》推薦

原則

資治通鑑

敏捷革命

如何鍛鍊自己的記憶力

簡單的邏輯學-讀後感

熱風-讀後感

論語-讀後感

孫子兵法-讀後感

思考

對過去的一點回顧

對寫部落格的一些思考

晚上打119的經歷

為動員一切力量爭取勝利而鬥爭

反對自由主義

實踐論

評價自己的標準

2020部落格總結

服務端團隊假期值班方案

專案流程管理

對專案管理的一些看法

對產品經理的一些思考

關於程式設計師職業發展的思考

關於程式碼review的思考