组合模式在对象间形成树形结构:
组合模式中基本对象和组合对象被一致对待:
无须关心对象有多少层,调用时只需在根部进行调用:
它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
应用场景:这个应用的地方也比较多,比如大多数系统的UI界面的导航菜单一般都是组合模式,再如Android里面的xml布局都是用的组合模式。在选择是否应用组合模式时,要考虑设计上的抉择,到底是要透明性更多一点,还是安全性更多一点,需要做一个平衡。
下面我们用前端界面左侧导航栏来做个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script>
class Folder {
constructor(name) {
this.name = name
this.fileList = []
}
add (file) {
this.fileList.push(file)
}
scan (fatherEle) {
console.log('文件夹', this.name)
let oul
if (fatherEle) {
let oli = document.createElement('li')
oli.innerHTML = this.name
oul = document.createElement('ul')
oli.appendChild(oul)
fatherEle.appendChild(oli)
} else {
let root = document.querySelector('#root')
oul = document.createElement('ul')
root.appendChild(oul)
}
for (let i = 0; i < this.fileList.length; i++) {
this.fileList[i].scan(oul)
}
}
}
class File {
constructor(name) {
this.name = name
}
scan (fatherEle) {
console.log('文件', this.name)
let oli = document.createElement('li')
oli.innerHTML = this.name
fatherEle.appendChild(oli)
}
}
let root = new Folder('root')
let folder1 = new Folder('folder1')
let folder2 = new Folder('folder2')
let folder3 = new Folder('folder3')
let folder4 = new Folder('folder4')
let folder5 = new Folder('folder5')
root.add(folder1)
root.add(folder2)
root.add(folder3)
root.add(folder4)
let file1 = new File('file1')
let file11 = new File('file11')
let file2 = new File('file2')
let file3 = new File('file3')
let file4 = new File('file4')
let file5 = new File('file5')
folder1.add(file1)
folder1.add(file11)
folder1.add(folder5)
folder2.add(file2)
folder3.add(file3)
folder4.add(file4)
folder5.add(file5)
root.scan()
</script>
</body>
</html>