组合模式
组合模式
定义
地球和一些其他行星围绕着太阳旋转,一个原子中,有许多电子围绕着原子核旋转,可以想象,太阳系也许是一个更大世界里的一个原子,地球只是围绕太阳旋转的一个电子,而我们身上的每个原子又是一个星系,原子核就是这个星系中的恒星,电子是围绕着恒星旋转的行星,一个电子中也许还包含了另一个宇宙,虽然这个宇宙还不能被显微镜看到,但可能真实存在
也许这个想法有些逆天,但在程序设计中,也有一些和“事物是由相似的子事物构成”类似的思想,组合模式就是用小的子对象来构建更大的对象,而这些小的子对象本身也许是由更小的“孙对象”构成的
1 |
|
其中,macroCommand 被称为组合对象,closeDoorCommand ,openPcCommand、openMusicCommand 都是叶对象,在 macroCommand 的 execute 方法里,并不执行真正的操作,而是遍历它所包含的叶对象,把真正的 execute 请求委托给这些叶对象
macroCommand 表现的像一个命令,但它实际上只是一组真正命令的“代理”,并非真正的代理,虽然结构上相似,但 macroCommand 只负责传递请求给叶对象,它的目的不在于控制叶对象的访问
用途
组合模式将对象组合成树形结构,以表示“部分-整体”的层次结构,除了用来表示树形结构外,组合模式的另一个好处是通过对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性
表示树形结构,通过上面的代码,很容易找到组合模式的一个优点:提供了一种遍历树形结构的方案,通过调用组合对象的 execute 方法,程序会递归调用组合对象下的叶对象的 execute 方法,所以只需要一次操作,便能依次完成关门,开机,打开音乐这几件事,组合模式可以非常方便地描述对象部分-整体层次结构
利用对象多态性统一对待组合对象和单个对象,利用对象的多态性表现,可以使客户端忽略组合对象和单个对象的不同,在组合模式中,客户将统一地使用组合结构中的所有对象,而不需要关心它究竟是组合对象还是单个对象
在实际开发中会给客户带来相当大的便利性,当我们往程序中添加一个命令的时候,并不关心这个命令是宏命令还是普通子命令,这点对于我们不重要,我们只需要确定它是一个命令,并且这个命令拥有可执行的 execute 方法,那么这个命令就可以被添加进程序中
当宏命令和普通子命令接收到执行 execute 方法的请求时,宏命令和普通子命令都会做他们各自认为正确的事,这些差异是隐藏在客户背后的,在客户看来,这种透明性可以让我们非常自由地扩展这个程序
注意的点
- 组合模式不是父子关系
- 对叶对象操作的一致性
- 双向映射的关系
- 用职责链模式提高组合模式性能
总结
在 JS 中组合模式可以使用树形方式创建对象的结构,可以把相同的操作应用在组合对象和单个对象上,在大多数情况下,都可以忽略掉组合对象和单个对象之间的差异,从而用一致的方式来处理他们
组合模式并不是完美的,它可能会产生一个这样的系统,系统中的每个对象看起来都与其他对象差不多,它们的区别只有在运行的时候才会显现出来,这会使代码难以理解,此外,如果通过组合模式创建了太多的对象,那么这些对象可能会让系统负担不起