目录
前言
1、代码写的多了,就知道一开始,我们其实就应该确定好最终的目标,然后进行各小功能的切片。
2、在编码的时候,应该养成提前做一些预判和设计的习惯。
3、
正文
理论
- 设计模式的目标:可复用。
- 面向对象的三大机制:
a. 封装:隐藏内部实现
b. 继承:复用现有代码
c. 多态:改写对象行为
- 如何解决复杂?
a. 结构话的思维->分解:分而治之
b. 面向对象的思维->抽象:忽视细节,泛化和理想化对象模型
- 什么是好的软件设计? 复用
- 重新认识面向对象:
a. 理解隔离变化
b. 各司其职: 各类各负责
c. 对象是什么?
面向对象设计八大原则
1. 依赖倒置原则
- 高层模块(稳定) 不应该依赖于低层模块(变化),二者都应依赖于抽象。
- 抽象(稳定)不应该依赖于实现细节。实现细节应该依赖于抽象。
- 上面讲的依赖都是:编译式依赖。
2. 开放封闭原则
- 对扩展开放,对更改封闭
- 类模块应该是可扩展的,但是不可修改。
3. 单一职责原则
- 一个类应该仅有一个引起它变化的原因。
- 变化的方向隐含着类的责任。
4. Liskov(里氏替换)原则
- 子类必须能够替换他们的基类。
- 继承表达类型抽象。
5. 接口隔离原则
- 不应该强迫客户程序依赖他们不用的方法。
- 接口应该小而完备。
6. 优先使用对象组合,而不是类继承。
- 类继承通常为白箱复用,对象组合通常为“黑箱复用”
- 继承在某种程度上破坏了封装性,子类父类耦合度较高
- 而对象组合则只要求被组合的对象具有良好定义的接口就可以了,耦合度低。
7. 封装变化点
- 使用封装来创建对象之间的分界层,让设计者在对象的一侧可以进行修改,而不会对另一侧产生不良的影响,从而实现层次建的松耦合。
8. 针对接口编程,而不是针对实现编程
- 不将变量类型声明为某个特定的类,而是声明为接口。
- 客户程序无需知道对象的具体类型,只需要知道对象具有的接口。
- 减少系统各部分的依赖关系,从而实现“高内聚,低耦合”的类型设计方案。
模板方法
一、装饰者模式
- **定义:**装饰模式是在不必改变原类和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
- 使用场景:
a.需要在运行时动态的给一个对象增加额外的职责时候
b.需要给一个现有的类增加职责,但是又不想通过继承的方式来实现的时候(应该优先使用组合而非继承),或者通过继承的方式不现实的时候(可能由于排列组合产生类爆炸的问题)。 - 理解:
第一,从构成上看,装饰器模式 = 代理模式 + 类继承。 也就是在代理模式的基础上,加了一堆 继承[代理类]的子类,从而进行扩展变化,并且还尽量减少了和原有类的联系。
第二,从功能上看,代理模式侧重的是“控制”,而装饰器模式侧重的是“扩展”。比如说,类A代理了类B,那么这两个类由于同一个接口的约束,它们的方法和实现的功能其实是一样的。而类C装饰了类D,那么这个时候类C不仅仅具备了类D的方法,同时还能加入自己的特殊逻辑。
代码在这里:Github地址
二、 观察者模式
1. 笔记
- 要善于剥离责任
- 实现接口的方法:提取子类中稳定的东西。然后实现成接口
- 接口或是抽象类一定要是稳定的。
- 将抽象与具体剥离开来,抽象层去做一个通知行为即可。
- 操作下一层的数据结构,最好用一些方法去操作,不要直接去操作。
动机:
将编译型依赖转化为运行时依赖
模式定义
三、适配器模式
四、外观模式
五、状态模式
六、策略模式
状态强调的状态的不同,状态不同,要做的事情不同(开心->买肯德基犒劳犒劳自己,不开心->明天请假不上班),聚焦在开心或者不开心上,而开心或者不开心具体要做什么不关心,你不开心明天辞职也可以
策略强调要做的事情不同会导致做事情的具体步骤不同,强调的是“做的步骤”,即行为、算法本身
总结:
1、Strategy 及其子类为组件提供了一系列可重用的算法,从而使得算法在运行时,方便的根据需要在各个算法之间进行切换。
2、 Strategy 提供了用条件判断语句以外的另一种选择,就是在消除条件判断语句,在消除解耦合。含有许多条件判断语句的代码通常都需要策略模式。
3、如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象 开销。
if else 其实是一种分支模式。比如只有一定要固定的情况,那么就可以用if else。
缓解性能问题。
用扩展的思想去面对这种变化。