先来看一段代码,这也是上一片命令模式中的宏命令的代码,
javascript
var closeDoorCommand = {
execute:function(){
console.log('关门')
}
};
var openDoorCommand = {
execute:function(){
console.log('开门')
}
}
var openQQCommand = {
execute:function(){
console.log('登陆QQ')
}
}
var MacroCommand = function(){
return {
commandsList:[],
add:function(command){
this.commandsList.push(command);
},
execute:function(){
for(let i=0,command;command=this.commandsList[i++];){
command.execute();
}
}
}
}
var macroCommand = MacroCommand();
macroCommand.add(closeDoorCommand);
macroCommand.add(openDoorCommand);
macroCommand.add(openQQCommand);
macroCommand.execute();
通过这段代码,很容易发现宏命令中包含一组字命令,他们组成了一个树形结构,这是一颗结构非常简单的树。
其中,macroCommand被称为组合对象,closeDoorCommand,openDoorCommand,openQQCommand都是叶对象。在macroCommand的execute的方法里,并不执行真正的操作,而是遍历它所包含的叶对象,把真正的execute请求委托给这些叶对象。
组合模式的用途
1.表示树形结构
2.利用对象多态性统一对待组合对象和单个对象。
目前的万能遥控器包含关门、开电脑、登陆QQ这3个功能,现在需要一个超级万能遥控器,可以控制家里所有的电器,他拥有以下功能:
1 打开空调,2 打开电视和音响 3. 关门、开电脑、登陆QQ
html
<button id="button">按我</button>
<script>
var MacroCommand = function(){
return {
commandsList:[],
add:function(command){
this.commandsList.push(command);
},
execute:function(){
for(let 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=new MacroCommand();
macroCommand1.add(openTvCommand);
macroCommand1.add(openSoundCommand);
// 关门、打开电脑和打开登陆QQ的命令
var closeDoorCommand = {
execute:function(){
console.log('关门')
}
};
var openDoorCommand = {
execute:function(){
console.log('开门')
}
}
var openQQCommand = {
execute:function(){
console.log('登陆QQ')
}
}
var macroCommand2 = MacroCommand();
macroCommand2.add(closeDoorCommand);
macroCommand2.add(openDoorCommand);
macroCommand2.add(openQQCommand);
// 现在把所有的命令组合成一个超级命令
var macroCommand = new MacroCommand();
macroCommand.add(openAcCommand);
macroCommand.add(macroCommand1);
macroCommand.add(macroCommand2);
// 最后给遥控器绑定超级命令
var setCommand = (function(command){
document.getElementById('button').onclick=function(){
command.execute();
}
})(macroCommand)
</script>
扫描文件夹的demo
javascript
// Folder
var Folder = function(name){
this.name=name;
this.files=[];
}
Folder.prototype.add=function(file){
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();
}
};
// file
var File = function(name){
this.name=name;
};
File.prototype.add=function(){
throw new Error('文件下面不能在添加文件');
};
File.prototype.scan=function(){
console.log('开始扫描文件:'+this.name);
};
// 接下来创建一些文件夹和文件对象,并且让他们组合成一棵树,这棵树就是我们F盘里现有的文件目录结构
var folder = new Folder('学习资料');
var folder1 = new Folder('JavaScript');
var folder2 = new Folder('jQuery');
var file1 = new File('javascript设计模式与开发实栈');
var file2 = new File('精通JQuery');
var file3 = new File('重构与模式');
folder1.add(file1);
folder2.add(file2);
folder.add(folder1);
folder.add(folder2);
folder.add(file3);
// 现在的需求是吧移动硬盘里的文件和文件夹都复制到这棵树中,假设我们已经得到了这些文件对象
var folder3 = new Folder('Node.js');
var file4=new File('深入浅出Node.js');
folder3.add(file4);
var file5=new File('javascript语言精髓与编程实践');
// 接下来就是把这些文件都添加到原有的树中
folder.add(folder3);
folder.add(file5);
folder.scan();
非原创,来源javascript设计模式与开发实践 -曾探