经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
每天一个设计模式之组合模式
来源:cnblogs  作者:GodBMW  时间:2018/12/17 9:43:26  对本文有异议

作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascriptpython两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :)

原文地址是:《每天一个设计模式之组合模式》

欢迎关注个人技术博客:godbmw.com。每周 1 篇原创技术分享!开源教程(webpack、设计模式)、面试刷题(偏前端)、知识整理(每周零碎),欢迎长期关注!

如果您也想进行知识整理 + 搭建功能完善/设计简约/快速启动的个人博客,请直接戳theme-bmw

0. 项目地址

1. 什么是“组合模式”?

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。

  1. 用小的子对象构造更大的父对象,而这些子对象也由更小的子对象构成
  2. 单个对象和组合对象对于用户暴露的接口具有一致性,而同种接口不同表现形式亦体现了多态性

2. 应用场景

组合模式可以在需要针对“树形结构”进行操作的应用中使用,例如扫描文件夹、渲染网站导航结构等等。

3. 代码实现

这里用代码模拟文件扫描功能,封装了FileFolder两个类。在组合模式下,用户可以向Folder类嵌套File或者Folder来模拟真实的“文件目录”的树结构。

同时,两个类都对外提供了scan接口,File下的scan是扫描文件,Folder下的scan是调用子文件夹和子文件的scan方法。整个过程采用的是深度优先

3.1 python3 实现

  1. class File: # 文件类
  2. def __init__(self, name):
  3. self.name = name
  4. def add(self):
  5. raise NotImplementedError()
  6. def scan(self):
  7. print('扫描文件:' + self.name)
  8. class Folder: # 文件夹类
  9. def __init__(self, name):
  10. self.name = name
  11. self.files = []
  12. def add(self, file):
  13. self.files.append(file)
  14. def scan(self):
  15. print('扫描文件夹: ' + self.name)
  16. for item in self.files:
  17. item.scan()
  18. if __name__ == '__main__':
  19. home = Folder("用户根目录")
  20. folder1 = Folder("第一个文件夹")
  21. folder2 = Folder("第二个文件夹")
  22. file1 = File("1号文件")
  23. file2 = File("2号文件")
  24. file3 = File("3号文件")
  25. # 将文件添加到对应文件夹中
  26. folder1.add(file1)
  27. folder2.add(file2)
  28. folder2.add(file3)
  29. # 将文件夹添加到更高级的目录文件夹中
  30. home.add(folder1)
  31. home.add(folder2)
  32. # 扫描目录文件夹
  33. home.scan()

执行$ python main.py, 最终输出结果是:

  1. 扫描文件夹: 用户根目录
  2. 扫描文件夹: 第一个文件夹
  3. 扫描文件:1号文件
  4. 扫描文件夹: 第二个文件夹
  5. 扫描文件:2号文件
  6. 扫描文件:3号文件

3.2 ES6 实现

  1. // 文件类
  2. class File {
  3. constructor(name) {
  4. this.name = name || "File";
  5. }
  6. add() {
  7. throw new Error("文件夹下面不能添加文件");
  8. }
  9. scan() {
  10. console.log("扫描文件: " + this.name);
  11. }
  12. }
  13. // 文件夹类
  14. class Folder {
  15. constructor(name) {
  16. this.name = name || "Folder";
  17. this.files = [];
  18. }
  19. add(file) {
  20. this.files.push(file);
  21. }
  22. scan() {
  23. console.log("扫描文件夹: " + this.name);
  24. for (let file of this.files) {
  25. file.scan();
  26. }
  27. }
  28. }
  29. let home = new Folder("用户根目录");
  30. let folder1 = new Folder("第一个文件夹"),
  31. folder2 = new Folder("第二个文件夹");
  32. let file1 = new File("1号文件"),
  33. file2 = new File("2号文件"),
  34. file3 = new File("3号文件");
  35. // 将文件添加到对应文件夹中
  36. folder1.add(file1);
  37. folder2.add(file2);
  38. folder2.add(file3);
  39. // 将文件夹添加到更高级的目录文件夹中
  40. home.add(folder1);
  41. home.add(folder2);
  42. // 扫描目录文件夹
  43. home.scan();

执行$ node main.js,最终输出结果是:

  1. 扫描文件夹: 用户根目录
  2. 扫描文件夹: 第一个文件夹
  3. 扫描文件: 1号文件
  4. 扫描文件夹: 第二个文件夹
  5. 扫描文件: 2号文件
  6. 扫描文件: 3号文件

4. 参考

  • 《JavaScript 设计模式和开发实践》
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号