組合模式針對於特定場景,如檔案管理、組織管理等,使用該模式能簡化管理,使程式碼變得非常簡潔。
UML類圖位置:https://www。processon。com/diagraming/609b375407912943913a4c13
本文程式碼連結為:https://github。com/shidawuhen/asap/blob/master/controller/design/16composite。go
1。定義
1。1組合模式
組合模式
:將物件組合成樹形結構以表示‘部分-整體’的層次結構。
組合模式使得使用者對單個物件和組合物件的使用具有一致性。
UML
:
1。2分析
單看UML圖可能不清晰,舉個栗子會容易一些。Composite是目錄,Leaf是目錄下的檔案,目錄和檔案都繼承自Component。目錄能夠增加、刪除檔案,可以展示目錄所在位置,檔案只能展示檔案所在位置。
對於目錄這種需求,有兩種實現方式。
第一種不使用組合模式,只用一個類,有2個核心變數
一個成員變量表明物件
是
檔案還是目錄
一個成員變數存放目錄下檔案列表,如果物件為檔案,則該變數為空
type FileSystemNode struct { isFile bool //表明是檔案還是目錄 subNodes []FileSystemNode //目錄下包含的內容}
第二種方案使用組合模式。雖然第一種方案能夠實現檔案管理的功能,但並不優雅。因為檔案和目錄是不同的,各自有各自的特性,將特有的內容放到一個類裡,
不滿足單一職責原則
。
所以我們可以將其拆分為兩個類:檔案類和目錄類。兩個類必須繼承自同一個父類,除了重複的功能可以複用外,更重要的一點是消除了兩個類呼叫上的區別,subNodes不需要做任何區分。而且這兩個類可以獨立進化,相互不影響,何樂而不為呢。
2。使用場景
組合模式在使用上,特別像深度優先遍歷或者廣度優先遍歷,一般用於組織結構、檔案管理上,這些功能都有共通點:個體和集體無論在功能上還是認知上都極為相似。
位元組跳動的協同辦公軟體-飛書,在文件管理部分,就極其適合使用組合模式,大家有時間可以嘗試一下,連結如下:https://www。feishu。cn/ ,其展現樣式如下所示:
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的思考