组合对象不做真正的操作,而是遍历它包含的叶对象,把请求委托给叶对象去处理。
- 更强大的宏命令
// 组合对象
var MacroCommand = function(){
return {
commandsList: [],
add: function( command ){
this.commandsList.push( command );
},
execute: function(){
for ( var i = 0, command; command = this.commandsList[ i++ ]; ){
command.execute();
}
}
}
};
// 叶对象
var openAcCommand = {
execute: function(){
console.log( '打开空调' );
}
};
1.最终都是一个对象形式
2.接口名必须一致 execute()
- 透明性带来的安全问题
组合模式就是为了让客户不用去了解组合对象和叶对象的区别。所以,客户可能会误操作调用叶对象的add方法。这种情况的改进如下:
var openTvCommand = {
execute: function(){
console.log( '打开电视' );
},
add: function(){
throw new Error( '叶对象不能添加子节点' );
}
};
- 扫描文件夹例子
具体实现与上面宏命令例子一样,只是采用 函数形式。 - 引用父对象
删除文件时,要先找到父对象,再从中删除对应的子对象。
1.增加 this.parent 属性
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 );
};
2.删除文件夹情况
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 );
}
}
};
3. 删除单个文件
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 );
}
}
};
网友评论