Skip to content

设计模式-组合模式

组合模式简单来将类似于一棵树,父节点和子节点有着类似的结构

graph TB A((组合对象)) B((叶对象)) C((叶对象)) D((叶对象)) E((组合对象)) F((叶对象)) G((叶对象)) H((叶对象)) I((叶对象)) A-->B A-->C A-->D A-->E E-->F E-->G E-->H E-->I

虽然上面说了类似“父子节点”这个字眼,但是组合模式并不是父子关系,更多的是部分-整体的关系.除了用来表示树形结构外,组合模式能更好的运用对象的多态特性.用户对单个对象和组合对象的使用有着一致性

扫描文件夹例子

我这里需要实现一个文件夹和文件的扫描的需求.当我选择某个文件夹的时候递归吧所有子文件和子文件夹下的所有文件都显示出来.同时我还需要实现文件夹和文件的删除功能.

js
var Folder = function (name) {
  this.name = name;
  this.files = [];
  this.parent = null;
};

Folder.prototype.add = function (file) {
  file.parent = this;
  this.files.push(file);
};

Folder.prototype.remove = function () {
  if (!this.parent) {
    return;
  }
  for (let i = 0; i < this.files.length; i++) {
    const file = this.files[i];
    if (file === this) {
      this.files.splice(i, 1);
    }
  }
};

Folder.prototype.scan = function () {
  console.log("开始扫描文件夹", this.name);

  // for (let i = 0; i < this.files.length; i++) {
  //   const file = this.files[i];
  //   file.scan()
  // }

  for (let i = 0, file, files = this.files; (file = files[i++]); ) {
    file.scan();
  }
};

File = function (name) {
  this.name = name;
  this.parent = null;
};
File.prototype.remove = function () {
  if (!this.parent) {
    return;
  }
  for (let i = 0; i < this.parent.files.length; i++) {
    const file = this.parent.files[i];
    if (file === this) {
      this.parent.files.splice(i, 1);
    }
  }
};
File.prototype.add = function () {
  throw new Error("文件下不能创建文件");
};

File.prototype.scan = function () {
  console.log("开始扫描文件", this.name);
};

// 测试
var rootFolder = new Folder("root folder");

var folder1 = new Folder("folder1");

var file1 = new File("file1");
var file2 = new File("file2");

var innerFolder = new Folder("inner folder");
var innerFile = new File("inner file");

rootFolder.add(folder1);
folder1.add(innerFolder);
folder1.add(file1);
folder1.add(file2);

innerFolder.add(innerFile);

file2.remove();

rootFolder.scan();


// 结果
// 开始扫描文件夹 root folder
// 开始扫描文件夹 folder1
// 开始扫描文件夹 inner folder
// 开始扫描文件 inner file
// 开始扫描文件 file1