前言
本系列文章主要根據《JavaScript設計模式與開發實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。
文章系列
概念
組合模式就是用小的子物件來構建更大的物件,而這些小的子物件本身也許是由更小的“孫物件”構成的。
場景
組合模式除了要求組合物件和葉物件擁有相同的介面之外,還有一個必要條件,就是對一組葉物件的操作必須具有一致性。
優缺點
優點
組合模式將物件組合成樹形結構,以表示“部分-整體”的層次結構。 除了用來表示樹形結 構之外,組合模式的另一個好處是通過物件的多型性表現,使得使用者對單個物件和組合物件的使 用具有一致性
缺點
它可能會產生一個這樣的系統:系統中的每個物件看起來都 與其他物件差不多。它們的區別只有在執行的時候會才會顯現出來,這會使程式碼難以理解。此外, 如果通過組合模式建立了太多的物件,那麼這些物件可能會讓系統負擔不起。
例子
掃描資料夾
這裡把檔案和資料夾無區別對待,檔案和資料夾都具有add和scan方法
var Folder = function (name) {
this.name = name;
this.files = [];
};
Folder.prototype.add = function (file) {
this.files.push(file);
};
Folder.prototype.scan = function () {
console.log(`開始掃描資料夾: ` + this.name);
for (var i = 0, file, files = this.files; file = files[i++];) {
file.scan();
}
};
/******************************* File ******************************/
var File = function (name) {
this.name = name;
};
File.prototype.add = function () {
throw new Error(`檔案下面不能再新增檔案`);
};
File.prototype.scan = function () {
console.log(`開始掃描檔案: ` + this.name);
};
var folder = new Folder(`學習資料`);
var folder1 = new Folder(`JavaScript`);
var folder2 = new Folder(`jQuery`);
var file1 = new File(`JavaScript 設計模式與開發實踐`);
var file2 = new File(`精通jQuery`);
var file3 = new File(`重構與模式`)
folder1.add(file1);
folder2.add(file2);
folder.add(folder1);
folder.add(folder2);
folder.add(file3);
var folder3 = new Folder(`Nodejs`);
var file4 = new File(`深入淺出Node.js`);
folder3.add(file4);
var file5 = new File(`JavaScript 語言精髓與程式設計實踐`);
folder.add(folder3);
folder.add(file5);
folder.scan();
增加刪除方法
我們需要增加一個父物件的引用
var Folder = function (name) {
this.name = name;
this.parent = null; //增加this.parent 屬性
this.files = [];
};
Folder.prototype.add = function (file) {
file.parent = this; //設定父物件
this.files.push(file);
};
Folder.prototype.scan = function () {
console.log(`開始掃描資料夾: ` + this.name);
for (var i = 0, file, files = this.files; file = files[i++];) {
file.scan();
}
};
Folder.prototype.remove = function () {
if (!this.parent) { //根節點或者樹外的遊離節點
return;
}
for (var files = this.parent.files, l = files.length - 1; l >= 0; l--) {
var file = files[l];
if (file === this) {
files.splice(l, 1);
}
}
};
var File = function (name) {
this.name = name;
this.parent = null;
};
File.prototype.add = function () {
throw new Error(`不能新增在檔案下面`);
};
File.prototype.scan = function () {
console.log(`開始掃描檔案: ` + this.name);
};
File.prototype.remove = function () {
if (!this.parent) { //根節點或者樹外的遊離節點
return;
}
for (var files = this.parent.files, l = files.length - 1; l >= 0; l--) {
var file = files[l];
if (file === this) {
files.splice(l, 1);
}
}
};
var folder = new Folder(`學習資料`);
var folder1 = new Folder(`JavaScript`);
var file1 = new Folder(`深入淺出Node.js`);
folder1.add(new File(`JavaScript 設計模式與開發實踐`));
folder.add(folder1);
folder.add(file1);
folder1.remove(); //移除資料夾
folder.scan();