作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用
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 設計模式和開發實踐》