设计模式之美
王争
前Google工程师,《数据结构与算法之美》专栏作者
立即订阅
20806 人已学习
课程目录
已更新 57 讲 / 共 100 讲
0/6登录后,你可以任选6讲全文学习。
开篇词 (1讲)
开篇词 | 一对一的设计与编码集训,让你告别没有成长的烂代码!
免费
设计模式学习导读 (3讲)
01 | 为什么说每个程序员都要尽早地学习并掌握设计模式相关知识?
02 | 从哪些维度评判代码质量的好坏?如何具备写出高质量代码的能力?
03 | 面向对象、设计原则、设计模式、编程规范、重构,这五者有何关系?
设计原则与思想:面向对象 (11讲)
04 | 理论一:当谈论面向对象的时候,我们到底在谈论什么?
05 | 理论二:封装、抽象、继承、多态分别可以解决哪些编程问题?
06 | 理论三:面向对象相比面向过程有哪些优势?面向过程真的过时了吗?
07 | 理论四:哪些代码设计看似是面向对象,实际是面向过程的?
08 | 理论五:接口vs抽象类的区别?如何用普通的类模拟抽象类和接口?
09 | 理论六:为什么基于接口而非实现编程?有必要为每个类都定义接口吗?
10 | 理论七:为何说要多用组合少用继承?如何决定该用组合还是继承?
11 | 实战一(上):业务开发常用的基于贫血模型的MVC架构违背OOP吗?
12 | 实战一(下):如何利用基于充血模型的DDD开发一个虚拟钱包系统?
13 | 实战二(上):如何对接口鉴权这样一个功能开发做面向对象分析?
14 | 实战二(下):如何利用面向对象设计和编程开发接口鉴权功能?
设计原则与思想:设计原则 (12讲)
15 | 理论一:对于单一职责原则,如何判定某个类的职责是否够“单一”?
16 | 理论二:如何做到“对扩展开放、修改关闭”?扩展和修改各指什么?
17 | 理论三:里式替换(LSP)跟多态有何区别?哪些代码违背了LSP?
18 | 理论四:接口隔离原则有哪三种应用?原则中的“接口”该如何理解?
19 | 理论五:控制反转、依赖反转、依赖注入,这三者有何区别和联系?
20 | 理论六:我为何说KISS、YAGNI原则看似简单,却经常被用错?
21 | 理论七:重复的代码就一定违背DRY吗?如何提高代码的复用性?
22 | 理论八:如何用迪米特法则(LOD)实现“高内聚、松耦合”?
23 | 实战一(上):针对业务系统的开发,如何做需求分析和设计?
24 | 实战一(下):如何实现一个遵从设计原则的积分兑换系统?
25 | 实战二(上):针对非业务的通用框架开发,如何做需求分析和设计?
26 | 实战二(下):如何实现一个支持各种统计规则的性能计数器?
设计原则与思想:规范与重构 (11讲)
27 | 理论一:什么情况下要重构?到底重构什么?又该如何重构?
28 | 理论二:为了保证重构不出错,有哪些非常能落地的技术手段?
29 | 理论三:什么是代码的可测试性?如何写出可测试性好的代码?
30 | 理论四:如何通过封装、抽象、模块化、中间层等解耦代码?
31 | 理论五:让你最快速地改善代码质量的20条编程规范(上)
32 | 理论五:让你最快速地改善代码质量的20条编程规范(中)
33 | 理论五:让你最快速地改善代码质量的20条编程规范(下)
34 | 实战一(上):通过一段ID生成器代码,学习如何发现代码质量问题
35 | 实战一(下):手把手带你将ID生成器代码从“能用”重构为“好用”
36 | 实战二(上):程序出错该返回啥?NULL、异常、错误码、空对象?
37 | 实战二(下):重构ID生成器项目中各函数的异常处理代码
设计原则与思想:总结课 (3讲)
38 | 总结回顾面向对象、设计原则、编程规范、重构技巧等知识点
39 | 运用学过的设计原则和思想完善之前讲的性能计数器项目(上)
40 | 运用学过的设计原则和思想完善之前讲的性能计数器项目(下)
设计模式与范式:创建型 (7讲)
41 | 单例模式(上):为什么说支持懒加载的双重检测不比饿汉式更优?
42 | 单例模式(中):我为什么不推荐使用单例模式?又有何替代方案?
43 | 单例模式(下):如何设计实现一个集群环境下的分布式单例模式?
44 | 工厂模式(上):我为什么说没事不要随便用工厂模式创建对象?
45 | 工厂模式(下):如何设计实现一个Dependency Injection框架?
46 | 建造者模式:详解构造函数、set方法、建造者模式三种对象创建方式
47 | 原型模式:如何最快速地clone一个HashMap散列表?
设计模式与范式:结构型 (6讲)
48 | 代理模式:代理在RPC、缓存、监控等场景中的应用
49 | 桥接模式:如何实现支持不同类型和渠道的消息推送系统?
50 | 装饰器模式:通过剖析Java IO类库源码学习装饰器模式
51 | 适配器模式:代理、适配器、桥接、装饰,这四个模式有何区别?
52 | 门面模式:如何设计合理的接口粒度以兼顾接口的易用性和通用性?
53 | 组合模式:如何设计实现支持递归遍历的文件系统目录树结构?
不定期加餐 (3讲)
加餐一 | 用一篇文章带你了解专栏中用到的所有Java语法
加餐二 | 设计模式、重构、编程规范等相关书籍推荐
春节特别加餐 | 王争:如何学习《设计模式之美》专栏?
免费
设计模式之美
登录|注册

53 | 组合模式:如何设计实现支持递归遍历的文件系统目录树结构?

王争 2020-03-04
结构型设计模式就快要讲完了,还剩下两个不那么常用的:组合模式和享元模式。今天,我们来讲一下组合模式(Composite Design Pattern)。
组合模式跟我们之前讲的面向对象设计中的“组合关系(通过组合来组装两个类)”,完全是两码事。这里讲的“组合模式”,主要是用来处理树形结构数据。这里的“数据”,你可以简单理解为一组对象集合,待会我们会详细讲解。
正因为其应用场景的特殊性,数据必须能表示成树形结构,这也导致了这种模式在实际的项目开发中并不那么常用。但是,一旦数据满足树形结构,应用这种模式就能发挥很大的作用,能让代码变得非常简洁。
话不多说,让我们正式开始今天的学习吧!

组合模式的原理与实现

在 GoF 的《设计模式》一书中,组合模式是这样定义的:
Compose objects into tree structure to represent part-whole hierarchies.Composite lets client treat individual objects and compositions of objects uniformly.
翻译成中文就是:将一组对象组织(Compose)成树形结构,以表示一种“部分 - 整体”的层次结构。组合让客户端(在很多设计模式书籍中,“客户端”代指代码的使用者。)可以统一单个对象和组合对象的处理逻辑。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《设计模式之美》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(14)

  • test
    把计算逻辑放在addSubNode和removeSubNode里面
    2020-03-04
    5
  • 八戒
    课堂讨论
    可以把计算文件数量和大小的逻辑抽出来,定义两个成员变量文件大小和文件数量;
    在每次addSubNode()和removeSubNode()的时候去调用计算逻辑,更新文件大小和文件数量;
    这样在调用countNumOfFiles和countSizeOfFiles的时候直接返回我们的成员变量就好了;
    当然如果这么做的话,那countNumOfFiles和countSizeOfFiles这两个方法的名字也不合适了,应该叫numOfFiles和sizeOfFiles
    2020-03-04
    4
  • 辣么大
    我想的一个思路是:每个节点新增一个field:parent,父链接指向它的上层节点,同时增加字段numOfFiles,sizeOfFiles。对于File节点:numOfFiles=1, sizeOfFiles=它自己的大小。对于Directory节点,是其子节点的和。删除、增加subnode时,只需要从下向上遍历一个节点的parent link,修改numOfFiles和sizeOfFiles。这样的话删除、新增subnode修改值的复杂度为树的深度,查询返回numOfFiles和sizeOfFiles复杂度为O(1)。
    2020-03-04
    1
    2
  • 小晏子
    Directory中缓存子节点数量和大小的信息,每次addSubNode和removeSubNode时,失效缓存的节点数量和大小的信息,这样每次查询的时候,如果缓存的信息有效,那么就直接返回,反之就遍历一遍,有点类似于数据库和cache数据同步的cache-aside方式,另外如果file本身大小如果有变化,也要有办法去失效Directory中的缓存信息,这就需要实现新的接口通知机制。
    2020-03-04
    1
  • 小兵
    课堂讨论首先想到了使用缓存,对于一个文件系统来说,文件的数量应当远高于文件夹的数量,可以在文件夹类增加一个成员变量,维护该层级下的文件数量,遍历的时候只需要遍历文件夹就可以了。
    2020-03-04
    1
  • Frank
    打卡 今日学习组合模式,收获如下:
    1. 对该模式有一个基本的认识
    2. 该模式在开发中使用的场景并不多。可以使用该模式的业务场景需要满足业务域能够形成树形结构
    3. 该模式是运用面向对象的思想来处理符合树形结构的业务场景,使得用户处理业务需求转化到处理整颗树或者数的一部分。
    2020-03-04
  • 唐朝农民
    那个算薪资的在实际生产中也不回这么用吧,虽然使用设计模式提高代码的可扩展性,但是需要循环,递归调用数据仓储层,如果员工一多肯定造成很大的性能影响,这也是我经常纠结的地方,有个时候为了减少访问数据库的次数,而不得不放弃更优雅的代码,请问这种情况该怎么破?
    2020-03-04
  • Wh1
    重构之后的FileSystemNode的子类Directory中的递归方法 countNumOfFiles() 是不是少了结束判断语句?
    2020-03-04
  • 南山
    真的是没有最适合,只有更适合
    实际工作中碰到过一个场景需要抽象出条件和表达式来解决的。一个表达式可以拥有N个子表达式以及条件,这个表达式还有一个属性and、or来决定所有子表达式/条件是全部成立还是只要有一个成立,这个表达式就成立。
    当时做的时候真是各种绕,这种场景真的非常适合组合模式,能大大简化代码的实现难度,提高可读、可维护性
    2020-03-04
  • Algo
    给每个目录进行分片,当要增加目录/文件或删除目录/文件时,根据分片找到对应的部分,然后增加或删除,且更新该分片的文件个数。总数是根据各分片进行汇总的数字。。。。
    2020-03-04
  • 陆老师
    可以加入fileSize,和fileCount字段,并用volatile修饰。文件的增删改操作,重新计算并赋值两个成员变量。其他线程读取到的数值也是最新的数值。
    2020-03-04
  • 课后题:
    这种方案应该多用于在服务启动时,从数据库/配置文件取出数据,按照格式缓存起来,外部调用的时候直接从缓存中去取,可以添加变量size,维护在各个节点下面,在add/remove时同时更新缓存和数据库(ps:这种数据一般很少变化吧?)
    2020-03-04
  • Jackey
    目录结构中存储这两项数据是否可行?每次新增或删除文件时就更新父节点的数据。这样的话就需要在结构体中增加一个“父指针”。
    2020-03-04
  • 守拙
    组合模式与其说是设计模式,不如说是数据结构与算法的抽象.
    就像小野二郎只做寿司一样, 组合模式专注于树形结构中单一对象(叶子节点)与组合对象(树节点)的递归遍历.
    2020-03-04
收起评论
14
返回
顶部