Javascript 设计模式 - 组合模式(Composite Pattern)

1,513 阅读2分钟

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

当我们想执行一个宏大的任务时,这个任务可以被细分为多层结构,组合模式可以让我们只发布一次执行命令,就能完成整个复杂的任务,屏蔽层级关系差异化问题

注意

  1. 组合模式不是父子关系,它们能够合作的关键是拥有相同的接口;
  2. 对叶对象操作的一致性,要对每个目标对象都实行同样的操作;
  3. 可用中介者模式处理双向映射关系,例如一个子节点同时在不同的父节点中存在(组织架构);
  4. 可用职责链模式提高组合模式性能,通过设置链条避免每次都遍历整个树;

应用场景

组合模式应树形结构而生,所以组合模式的使用场景就是出现树形结构的地方。

  • 命令分发: 只需要通过请求树的最顶层对象,便能对整棵树做统一的操作。在组合模式中增加和删除树的节点非常方便,并且符合开放-封闭原则
  • 统一处理: 统一对待树中的所有对象,忽略组合对象和叶对象的区别;

比如: 文件目录显示,多级目录呈现等树形结构数据的操作。

举例:文件系统操作

// 文件夹
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();

总结

组合模式可以让我们使用树形方式创 建对象的结构。我们可以把相同的操作应用在组合对象和单个对象上。在大多数情况下,我们都 可以忽略掉组合对象和单个对象之间的差别,从而用一致的方式来处理它们。

参考

JavaScript设计模式与开发实践