- 手中无剑、心中无剑
- 手中有剑、心中无剑
- 手中有剑、心中有剑
- 手中无剑、心中无剑
目标
- 管理变化,提高复用
- 误区
- 模式只按照算法去学习
- 分析理解结构
- 理解代码的调用流程
- 初级但远不够
- 核心
- 所有的设计是不是达到提高复用的目标
- 误区
两个手段
- 分解
- 对事物的认知,首先要分解,降低认知的难度
- 抽象
- 但还要上升到抽象
- 对一类物事进行统一的管理
八大原则
- 依赖倒置原则(DIP)
- 开放封装原则(OCP)
- 单一职责原则(SRP)
- Liskov 替换原则 (LSP)
- 接口隔离原则 (ISP)
- 对象组合优于类继承
- 封装变化点
- 面向接口编程
重构技法
- 静态 -> 动态
- 早绑定 -> 晚绑定
- 继承 -> 组合
- 编译时依赖 -> 运行时依赖
- 紧耦合 -> 松耦合
cpp 对象模型
把所有的类名换成A/B/C,把方法名换成f1/f2之后,会发现一个非常雷同的结构
重构之后的代码特征如3号图所示。所有的模式都归属到第3种结构
- 第1种继承
- cpp内存布局是把B中所有数据成员嵌入在A里面,而且是在A成员前面
- 第2种组合
- B也是放在A前面
- 继承与组合在内存布局上一样
- 所以有继承转组合,慎用继承多用组合
- 但这里的组合,是指第3种组合形式
- 第3种组合一个指针
- 组合对象B,B不能有变化,只能是自己,不能是它的子类对象
- 如果传子类对象,会出现对象切割
- 对象指针有灵活性
- 可以指向B也可以指向B的子类
- 所有模式都是通过指针指向多态对象来表达灵活性
- 指针指向多态对象变成了松耦合结构的对象模型基础
- 第1、2种都是紧耦合的对象模型
- 第3种是松耦合的对象模型
- 因为指针所以灵活
- 所谓灵活:就是它可以是B和B的子类
稳定点和变化点
- 所有的模式都要关注其稳定点和变化点
- 如果稳定点不满足
- 这个模式就不行了(不适用)
- 出现变化点,模式才有意义
- 设计模式出现的宗旨是管理变化
- 现实中软件的变化点是服从正太分布的
- 在变化点处应用设计模式
什么时候不用模式
- 代码可读性差时
- 读《重构·可读代码的艺术》,知道什么叫可读性
- 模式是在这些之后做的,不是在之前做的
- 需求理解很浅时
- 先做出最初的版本
- 做到第2、3版才做模式
- 变化没有显现时
- 不恰当的预测变化
- 不是系统的关键依赖点
- 项目没用利用价值时
- 外包软件,做完不再维护了
- 做产品的公司,第2、3版要修改的就少了,软件的复用性高
- 项目将要发布时
- 保证软件的正确性
经验之谈
- 不要为模式而模式
- 关注抽象类和接口
- 抽象类表达的是很高的水平
- 多写基类、接口
- 理清变化点和稳定点
- 审视依赖关系
- 要有Framework和Application的区隔思维
- 应用开发人员,看到框架和模式,找到哪些是扩展点
- 良好的设计是演化的结果
- 不是一步到位
设计模式的成长路径
- 手中无剑、心中无剑
- 见模式而不知
- 手中有剑、心中无剑
- 可以识别出来
- 可以应用
- 手中有剑、心中有剑
- 做为框架开发人员
- 为应用设计某些模式
- 深入理解设计模式在关注依赖关系过程中的解决方案
- 同时每个具体模式也知道怎么表达
- 3~4、7~8年
- 手中无剑、心中无剑
- 忘掉模式、只有原则