TIP

组合模式将对象组合成树形结构,以表示“部分-整体”的层次结构。组合模式还可以通过对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性。

# 案例:扫描文件夹

文件夹和文件之间的关系,非常适合用组合模式来描述。文件夹里既可以包含文件,又可以包含其他文件夹,最终可能组合成一棵树。

//文件夹
var Folders = function (name) {
  this.name = name;
  this.list = [];
}
        
Folders.prototype.add = function (file) {
  this.list.push(file);
}
        
Folders.prototype.scan = function () {
  console.log("开始浏览文件夹:" + this.name);
  for (var i=0, file; file = this.list[i++];) {
    file.scan();
  }
}
        
//文件
var Files = function (name) {
  this.name = name;
}
        
Files.prototype.add = function () {
  throw new Error("文件不支持添加操作");
}

Files.prototype.scan=function () {
  console.log("开始浏览文件:" + this.name)
}

var folder = new Folders("学习资料");
var folder1 = new Folders("JavaScript");
var folder2 = new Folders("JQuery");

var file1 = new Files("JavaScript设计模式与开发实践");
var file2 = new Files("精通JQuery");
var file3 = new Files("重构与模式");

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()

# 组合模式注意点

  1. 组合模式不是父子关系 组合对象包含一组叶对象,但Leaf并不是Composite的子类。组合对象把请求委托给它所包含的所有叶对象,它们能够合作的关键是拥有相同的接口。

  2. 对叶对象操作的一致性 组合模式除了要求组合对象和叶对象拥有相同的接口之外,还有一个必要条件,就是对一组叶对象的操作必须具有一致性。

  3. 双向映射关系

  4. 用职责链模式提高组合模式性能

# 何时使用组合模式

  • 表示对象的整体-部分层次结构
  • 客户希望统一对待树中的所有对象