一个目标:管理变化,提高复用
掌握设计模式一个核心目标:管理变化,提高复用。在使用设计模式中发现并没有实现复用,这就和设计初衷相违背了,说明代买写的不好。
两种手段:分解VS.抽象
在代码设计中,该开始想要怎样面向对象先要分解,比如这是梨,这是苹果,这是香蕉建立这杨分解的思维,知道它们不同。但是呢我们很快建立抽象的思维,知道这一类都归属水果,然后就可以在思维管理里面或程序管理里面针对抽象进行统一的管理,比如水果有哪些功能的特征。
八大原则
- 依赖倒置原则(DIP)
- 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定) 。
- 抽象(稳定)不应该依赖于实现细节(变化) ,实现细节应该依赖于抽象(稳定)。
- 开放封闭原则(OCP)
- 对扩展开放,对更改封闭。
- 类模块应该是可扩展的,但是不可修改。
- 单一职责原则(SRP)
- 一个类应该仅有一个引起它变化的原因。
- 变化的方向隐含着类的责任。
- Liskov 替换原则(LSP)
- 子类必须能够替换它们的基类(IS-A)。
- 继承表达类型抽象。
- 接口隔离原则(ISP)
- 不应该强迫客户程序依赖它们不用的方法。
- 接口应该小而完备。
- 优先使用对象组合,而不是类继承
- 类继承通常为“白箱复用”,对象组合通常为“黑箱复用”。
- 继承在某种程度上破坏了封装性,子类父类耦合度高。
- 而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。
- 封装变化点
- 使用封装来创建对象之间的分界层,让设计者可以在分界层的
- 一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
- 针对接口编程,而不是针对实现编程
- 不将变量类型声明为某个特定的具体类,而是声明为某个接口。
- 客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
- 减少系统中各部分的依赖关系,从而实现”高内聚、松耦合"的类型设计方案。
重构技法
- 静态 → 动态
- 早绑定→ 晚绑定
- 继承→ 组合
- 编译时依赖→ 运行时依赖
- 紧耦合→ 松耦合
从封装变化角度对模式分类
C++ 对象模型
几乎所有模式都归属第三种结构。继承和组合在C++内存模型上没有太大的区别,所以慎用继承,优先组合,不过是带指针的组合,如果是第二种会发生对象切割,而用指针更灵活,还可以指向它的子类。从耦合性来看,前两种是紧耦合,第三种松耦合。
关注变化点和稳定点
设计模式的宗旨是:管理变化,提高复用。如果是所有都是变化的或稳定的,那用设计模式也没有意义,设计模式是在管理变化实现稳定与变化隔离。
什么时候不用模式
- 代码可读性很差时
- 需求理解还很浅时
- 变化没有显现时
- 不是系统的关键依赖点
- 项目没有复用价值时
- 项目将要发布时
经验之谈
- 不要为模式而模式
- 关注抽象类&接口
- 理清变化点和稳定点
- 审视依赖关系
- 要有Framework和Application的区隔思维
- 良好的设计是演化的结果
设计模式成长之路
- “手中无剑,心中无剑”: 见模式而不知
- “手中有剑,心中无剑”: 可以识别模式,作为应用开发人员使用模式
- “手中有剑,心中有剑”: 作为框架开发人员为应用设计某些模式
- “手中无剑,心中有剑”: 忘掉模式,只有原则