1.什么是设计模式?
每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次的使用该方案而不必重复劳动。——Christopher Alexander
个人理解:是人类面临同类问题所提出的可复用解决方案。
2.软件设计的复杂性
建筑商从来不会想给一栋已经建好100层的楼房再新修一座地下室,这样花费极大且注定失败,然而令人惊奇的是,软件系统的用户在要求做出类似的改变时却不会仔细考虑,而且他们觉得这只是需要简单编程的事。
个人解读:软件设计复杂的根本原因在于变化,客户需求的变化、技术平台的变化,开发团队的变化,市场环境的变化等等,这样的变化时刻的冲击着我们已经设计编写好的软件体系结构。
3.如何解决这种复杂性
解决复杂问题的方法一般有两种做法:
-
分解:人们面临复杂问题有一个常见做法,就是分解思维,将大问题分解为若干的小问题,将复杂问题分解为多个简单问题。
-
抽象:从更高层次来讲,人们处理复杂性问题有一个通用的方法,由于不能掌握全部的复杂对象,我们选择忽略它的非本质细节,而去处理泛化和理想化了的对象模型。
4.软件设计的目标
什么是好的软件设计?软件设计的金科玉律——重用、抵御变化,抽象思维往往相对于分解思维有更好的重用性。
5.什么是面向对象
(1)向下的底层思维
面向对象三大机制:
- 封装:隐藏内部实现
- 继承:复用现有代码
- 多态:改写对象行为
(2)向上的抽象思维
- 从规格上面来看,对象是一系列可以被使用的公共接口。
- 从概念上面来看,对象是某种拥有责任的抽象
面向对象的方式更加注重抽象出来被处理问题所涉及的相关方,划定这些相关方的职责边界,代码的编写者不再需要过分关心整个问题的处理流程,转而关注处理问题需要哪些相关方怎样来合作完成问题。面向对象设计语言提供的这样的抽象能力一是增强了处理复杂问题的能力,二是增强了我们构建的软件能够更加适应软件的变化点。
6.面向对象设计原则?
- 依赖倒置原则
高层模块不能依赖于低层模块,二者都应该依赖抽象。抽象不应该依赖于细节,实现细节应该依赖于抽象。
因为在设计上,高层模块需要保持其稳定性,高层模块依赖了低层模块会导致低层模块的变化引起高层模块的变化,所以二者要依赖于抽象,抽象便隔离了这种变化。
- 开闭原则
对扩展开放,对修改关闭。
类模块应该是可以扩展的,但是不可以修改。因为当类模块发生修改的时候,该类模块的相关功能都需要重新编译调试部署测试,所以我们尽量的保证对修改关闭。
- 单一职责原则
一个类只有一个引起他发生变化的原因。
一个类变化的方向隐含了一个责任,我们往往不希望一个类有多个变化的方向,例如假设一个类有n个变化的方向,产生变化的种类时候就是乘积式的爆发,若是用抽象隔离开这些变化的话,产生变化的种类就是和式增长。
- 里氏替换原则
子类能完全替换他的基类
比如不期望有异常的方法,就不能在子类抛一个异常,假设父类的某个非私有方法子类没有,这个子类就不能继承这个类。
- 接口隔离原则
不应该强迫客户程序依赖他们不用的方法。
接口应该小而完备。
- 组合/聚合复用原则
组合比继承耦合度低。在多个变化点的时候也可以防止子类数量乘积式的爆炸增长。
- 封装变化点
使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧修改,而不会对另一侧产生不良的影响,实现层次间的松耦合。
- 面向接口编程,而不是面向实现编程
7.从封装变化角度对模式分类
(1)组件协作
- 模板方法
- 策略模式
- 观察者模式
(2)单一职责
- 装饰器模式
- 桥模式
(3)对象创建
- 工厂方法
- 抽象工厂
- 原型模式
- 建造者模式
(4)对象性能
- 单例模式
- 享元模式
(5)接口隔离
- 外观模式
- 代理模式
- 中介者模式
- 适配器模式
(6)状态变化
- 备忘录模式
- 状态模式
(7)数据结构
- 组合模式
- 迭代器模式
- 职责链模式
(8)行为变化
- 命令模式
- 访问者模式
(9)领域问题
- 解释器模式