一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情。
导言
在面向对象编程语言中,有一条非常经典的设计原则:组合优于继承。尽量少用继承来进行扩展,避免不必要的各个类或对象间的关系。
还有个有趣的小故事:从前有座山,山里有个庙,庙里有个老和尚和小和尚,老和尚给小和尚讲故事...,其实我们在一个系统中,我们也可能是另一个更大系统的一个组合,并且我们所在系统的更小维度也是由很多子系统组成。
组合模式
组合模式理解起来比较简单,就是系统的功能是由不同子系统对象功能组合而成。
let closeDoorCommand = {
execute: function () {
console.log('执行关门命令')
}
}
let openComputeCommand = {
execute: function () {
console.log('执行打开电脑命令')
}
}
let openWechatCommand = {
execute: function () {
console.log('执行打开微信命令')
}
}
let MacroCommand = function(){
return {
commandList: [],
add: function (command) {
this.commandList.push(command)
},
execute: function () {
for (let i = 0; i < this.commandList.length; i++) {
this.commandList[i].execute()
}
}
}
}
let macroCommand = MacroCommand()
macroCommand.add(closeDoorCommand) // 执行关门命令
macroCommand.add(openComputeCommand) // 执行打开电脑命令
macroCommand.add(openWechatCommand) // 执行打开微信命令
macroCommand.execute()
使用场景
组合模式如果合理运用,可以大大提高代码的可复用性。一般来说,组合模式常用于以下这两种情况:
-
表示对象的部分-整体层次结构。组合模式可以方便地构造一棵树来表示对象的部分-整体结构。特别是我们在开发期间不确定这棵树到底存在多少层次的时候。在树的构造最终完成之后,只需要通过请求树的最顶层对象,便能对整棵树做统一的操作。在组合模式中增加和删除树的节点非常方便,并且符合开闭原则。
-
统一对待树中的所有对象。组合模式使开发中可以忽略组合对象和子对象的区别,在面对这棵树的时候,不用关心当前正在处理的对象是组合对象还是子对象,也就不用写一堆if、else语句来分别处理它们。组合对象和子对象会各自做自己正确的事情,这是组合模式最重要的能力。