1. 定义
组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更小的“孙对象”构成的。
2. 用途
组合模式的好处
- 将对象组合成树形结构,以表示“部分-整体”的层次结构
- 组合模式提供了一种遍历树形结构的方案,通过调用组合对象的execute方法,程序会递归调用组合对象下面的叶对象的execute方法
- 通过对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性
- 利用对象的多态性表现,可以使客户端忽略组合对象和单个对象的不同。在组合模式中,客户将统一地使用组合结构中的所有对象,而不需要关心它究竟是组合对象还是单个对象
3. 请求在组合树中的传递过程
请求从树最顶端的对象往下传递,如果当前处理请求的对象是叶对象(普通子命令),叶对象自身会对请求做出相对应的处理,如果当前处理请求的对象是组合对象(宏命令),组合对象则会遍历他属下的子节点,将请求继续传递给这些子节点
4. 注意点
- 组合模式不是父子关系
- 组合模式是HAS-A(聚合)的关系,而不是IS-A,组合对象包含一组叶对象,但是leaf并不是composite的子类。组合对象把请求委托给他所包含的所有叶对象,他们能够合作的关键是拥有了相同的接口
- 对叶对象操作的一致性
- 组合模式除了要求组合和叶对象拥有相同的接口之外,还有一个必要条件,就是对一组叶对象的操作必须具有一致性
- 双向映射关系
- 用职责链模式提高组合模式性能
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( '打开空调' );
}
};
/**********家里的电视和音响是连接在一起的,所以可以用一个宏命令来组合打开电视和打开音响的命令
*********/
var openTvCommand = {
execute: function(){
console.log( '打开电视' );
}
};
var openSoundCommand = {
execute: function(){
console.log( '打开音响' );
}
};
var macroCommand1 = MacroCommand();
macroCommand1.add( openTvCommand );
macroCommand1.add( openSoundCommand );
/*********关门、打开电脑和打登录 QQ 的命令****************/
var closeDoorCommand = {
execute: function(){
console.log( '关门' );
}
};
var openPcCommand = {
execute: function(){
console.log( '开电脑' );
}
};
var openQQCommand = {
execute: function(){
console.log( '登录 QQ' );
}
};
var macroCommand2 = MacroCommand();
macroCommand2.add( closeDoorCommand );
macroCommand2.add( openPcCommand );
macroCommand2.add( openQQCommand );
/*********现在把所有的命令组合成一个“超级命令”**********/
var macroCommand = MacroCommand();
macroCommand.add( openAcCommand );
macroCommand.add( macroCommand1 );
macroCommand.add( macroCommand2 );
/*********最后给遥控器绑定“超级命令”**********/
var setCommand = (function( command ){
document.getElementById( 'button' ).onclick = function(){
command.execute();
}
})( macroCommand );
5. 适用场景
- 表示对象的部分-整体层次结构
- 客户希望统一对待树中的所有对象