JavaScript设计模式笔记(六)组合模式

组合模式的定义

组合模式将对象组合成树形结构,以表示“部分-整体”的层次结构。
曾探《JavaScript设计模式与开发实践》
组合模式用于处理组合对象的请求。

更强大的宏命令

关于宏命令的实现,我在命令模式的笔记中已经提及了。

在组合模式中,可以对宏命令做更好的处理,将一些小的宏命令合成大的宏命令,下面引用《JavaScript设计模式与开发实践》的代码来说明这点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<html>

<body>
<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 = MacroCommand();
macroCommand1.add(openTvCommand);
macroCommand1.add(openSoundCommand);

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);
</script>
</body>

</html>

结果

这里的命令发出是以链式的方法发出的,一个大的宏命令告知其包含的命令执行execute方法,若其中还有宏命令,则继续告知,若为普通命令,则直接执行execute方法。

该例子的树形结构为

组合模式的注意点

  1. 组合模式不是父子关系
    组合模式是一种HAS-A的关系,而不是IS-A的关系。
  • HAS-A:一种事物为另一种事物上的一个部件

  • IS-A:一种事物为另一种事物中的一种分类

组合对象包含一组叶对象,方法的真正执行是在叶对象上,其他对象方法的执行实际上起到了一个命令传递的作用。

  1. 命令方法的一致性
    要保证对象能从根一直传递到叶,必须保证方法名是相同的,如上面例子中都是execute。

  2. 一个对象不能有两个“父对象”
    这里的“父对象”指将命令传给该对象的对象,如果一个对象有两个“父对象”,意味着在命令传递过程中,它的方法会被执行两次,假如它不是叶对象,其下的所有对象的方法都会被执行两次。

组合模式的优点

  1. 对于树中的对象“平等”对待

不管树中的对象是组合对象或者叶节点对象,都执行相同的方法

  1. 迭代树关系数据的便利性

只需要执行根节点的方法就可以对整棵树执行该方法,对迭代一棵树来说很方便

组合模式的缺点

  1. 树结构中对象的相似性过高

为了保证树结构中的节点能被遍历,每个节点的方法大都是相同的,这样在看代码时很难区分对象,只有在执行的时候才能区分对象

  1. 创建过多的对象

组合模式除了为每一个执行方法的对象构建一个对象,还要构建多个组合对象来构成最后完整的树结构,在这个过程中可能会构建过多的对象,而系统可能担负不起过多的对象。


参考自曾探的《JavaScript设计模式与开发实践》