作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :)
javascript
python
原文地址是:《每天一个设计模式之组合模式》
欢迎关注个人技术博客:godbmw.com。每周 1 篇原创技术分享!开源教程(webpack、设计模式)、面试刷题(偏前端)、知识整理(每周零碎),欢迎长期关注!
如果您也想进行知识整理 + 搭建功能完善/设计简约/快速启动的个人博客,请直接戳theme-bmw
组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。
组合模式可以在需要针对“树形结构”进行操作的应用中使用,例如扫描文件夹、渲染网站导航结构等等。
这里用代码模拟文件扫描功能,封装了File和Folder两个类。在组合模式下,用户可以向Folder类嵌套File或者Folder来模拟真实的“文件目录”的树结构。
File
Folder
同时,两个类都对外提供了scan接口,File下的scan是扫描文件,Folder下的scan是调用子文件夹和子文件的scan方法。整个过程采用的是深度优先。
scan
class File: # 文件类 def __init__(self, name): self.name = name def add(self): raise NotImplementedError() def scan(self): print('扫描文件:' + self.name)class Folder: # 文件夹类 def __init__(self, name): self.name = name self.files = [] def add(self, file): self.files.append(file) def scan(self): print('扫描文件夹: ' + self.name) for item in self.files: item.scan()if __name__ == '__main__': home = Folder("用户根目录") folder1 = Folder("第一个文件夹") folder2 = Folder("第二个文件夹") file1 = File("1号文件") file2 = File("2号文件") file3 = File("3号文件") # 将文件添加到对应文件夹中 folder1.add(file1) folder2.add(file2) folder2.add(file3) # 将文件夹添加到更高级的目录文件夹中 home.add(folder1) home.add(folder2) # 扫描目录文件夹 home.scan()
class File: # 文件类
def __init__(self, name):
self.name = name
def add(self):
raise NotImplementedError()
def scan(self):
print('扫描文件:' + self.name)
class Folder: # 文件夹类
self.files = []
def add(self, file):
self.files.append(file)
print('扫描文件夹: ' + self.name)
for item in self.files:
item.scan()
if __name__ == '__main__':
home = Folder("用户根目录")
folder1 = Folder("第一个文件夹")
folder2 = Folder("第二个文件夹")
file1 = File("1号文件")
file2 = File("2号文件")
file3 = File("3号文件")
# 将文件添加到对应文件夹中
folder1.add(file1)
folder2.add(file2)
folder2.add(file3)
# 将文件夹添加到更高级的目录文件夹中
home.add(folder1)
home.add(folder2)
# 扫描目录文件夹
home.scan()
执行$ python main.py, 最终输出结果是:
$ python main.py
扫描文件夹: 用户根目录扫描文件夹: 第一个文件夹扫描文件:1号文件扫描文件夹: 第二个文件夹扫描文件:2号文件扫描文件:3号文件
扫描文件夹: 用户根目录
扫描文件夹: 第一个文件夹
扫描文件:1号文件
扫描文件夹: 第二个文件夹
扫描文件:2号文件
扫描文件:3号文件
// 文件类class File { constructor(name) { this.name = name || "File"; } add() { throw new Error("文件夹下面不能添加文件"); } scan() { console.log("扫描文件: " + this.name); }}// 文件夹类class Folder { constructor(name) { this.name = name || "Folder"; this.files = []; } add(file) { this.files.push(file); } scan() { console.log("扫描文件夹: " + this.name); for (let file of this.files) { file.scan(); } }}let home = new Folder("用户根目录");let folder1 = new Folder("第一个文件夹"), folder2 = new Folder("第二个文件夹");let file1 = new File("1号文件"), file2 = new File("2号文件"), file3 = new File("3号文件");// 将文件添加到对应文件夹中folder1.add(file1);folder2.add(file2);folder2.add(file3);// 将文件夹添加到更高级的目录文件夹中home.add(folder1);home.add(folder2);// 扫描目录文件夹home.scan();
// 文件类
class File {
constructor(name) {
this.name = name || "File";
}
add() {
throw new Error("文件夹下面不能添加文件");
scan() {
console.log("扫描文件: " + this.name);
// 文件夹类
class Folder {
this.name = name || "Folder";
this.files = [];
add(file) {
this.files.push(file);
console.log("扫描文件夹: " + this.name);
for (let file of this.files) {
file.scan();
let home = new Folder("用户根目录");
let folder1 = new Folder("第一个文件夹"),
folder2 = new Folder("第二个文件夹");
let file1 = new File("1号文件"),
file2 = new File("2号文件"),
file3 = new File("3号文件");
// 将文件添加到对应文件夹中
folder1.add(file1);
folder2.add(file2);
folder2.add(file3);
// 将文件夹添加到更高级的目录文件夹中
home.add(folder1);
home.add(folder2);
// 扫描目录文件夹
home.scan();
执行$ node main.js,最终输出结果是:
$ node main.js
扫描文件夹: 用户根目录扫描文件夹: 第一个文件夹扫描文件: 1号文件扫描文件夹: 第二个文件夹扫描文件: 2号文件扫描文件: 3号文件
扫描文件: 1号文件
扫描文件: 2号文件
扫描文件: 3号文件
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728