作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用 和`python`兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式 :) 原文地址是: "《每天一個設計模式之組合模式》" 歡迎關註個人技術博客: "godbmw.com" 。每周 1 篇原創技術分 ...
作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用
javascript
和python
兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式 :)
原文地址是:《每天一個設計模式之組合模式》
歡迎關註個人技術博客:godbmw.com。每周 1 篇原創技術分享!開源教程(webpack、設計模式)、面試刷題(偏前端)、知識整理(每周零碎),歡迎長期關註!
如果您也想進行知識整理 + 搭建功能完善/設計簡約/快速啟動的個人博客,請直接戳theme-bmw
0. 項目地址
1. 什麼是“組合模式”?
組合模式,將對象組合成樹形結構以表示“部分-整體”的層次結構。
- 用小的子對象構造更大的父對象,而這些子對象也由更小的子對象構成
- 單個對象和組合對象對於用戶暴露的介面具有一致性,而同種介面不同表現形式亦體現了多態性
2. 應用場景
組合模式可以在需要針對“樹形結構”進行操作的應用中使用,例如掃描文件夾、渲染網站導航結構等等。
3. 代碼實現
這裡用代碼模擬文件掃描功能,封裝了File
和Folder
兩個類。在組合模式下,用戶可以向Folder
類嵌套File
或者Folder
來模擬真實的“文件目錄”的樹結構。
同時,兩個類都對外提供了scan
介面,File
下的scan
是掃描文件,Folder
下的scan
是調用子文件夾和子文件的scan
方法。整個過程採用的是深度優先。
3.1 python3 實現
class File: # 文件類
def __init__(self, name):
self.name = name
def add(self):
raise NotImplementedError()
def scan(self):
print('掃描文件:' + self.name)
class Folder: # 文件夾類
def __init__(self, name):
self.name = name
self.files = []
def add(self, file):
self.files.append(file)
def scan(self):
print('掃描文件夾: ' + self.name)
for item in self.files:
item.scan()
if __name__ == '__main__':
home = Folder("用戶根目錄")
folder1 = Folder("第一個文件夾")
folder2 = Folder("第二個文件夾")
file1 = File("1號文件")
file2 = File("2號文件")
file3 = File("3號文件")
# 將文件添加到對應文件夾中
folder1.add(file1)
folder2.add(file2)
folder2.add(file3)
# 將文件夾添加到更高級的目錄文件夾中
home.add(folder1)
home.add(folder2)
# 掃描目錄文件夾
home.scan()
執行$ python main.py
, 最終輸出結果是:
掃描文件夾: 用戶根目錄
掃描文件夾: 第一個文件夾
掃描文件:1號文件
掃描文件夾: 第二個文件夾
掃描文件:2號文件
掃描文件:3號文件
3.2 ES6 實現
// 文件類
class File {
constructor(name) {
this.name = name || "File";
}
add() {
throw new Error("文件夾下麵不能添加文件");
}
scan() {
console.log("掃描文件: " + this.name);
}
}
// 文件夾類
class Folder {
constructor(name) {
this.name = name || "Folder";
this.files = [];
}
add(file) {
this.files.push(file);
}
scan() {
console.log("掃描文件夾: " + this.name);
for (let file of this.files) {
file.scan();
}
}
}
let home = new Folder("用戶根目錄");
let folder1 = new Folder("第一個文件夾"),
folder2 = new Folder("第二個文件夾");
let file1 = new File("1號文件"),
file2 = new File("2號文件"),
file3 = new File("3號文件");
// 將文件添加到對應文件夾中
folder1.add(file1);
folder2.add(file2);
folder2.add(file3);
// 將文件夾添加到更高級的目錄文件夾中
home.add(folder1);
home.add(folder2);
// 掃描目錄文件夾
home.scan();
執行$ node main.js
,最終輸出結果是:
掃描文件夾: 用戶根目錄
掃描文件夾: 第一個文件夾
掃描文件: 1號文件
掃描文件夾: 第二個文件夾
掃描文件: 2號文件
掃描文件: 3號文件
4. 參考
- 《JavaScript 設計模式和開發實踐》