设计模式的概念最早是由 `克里斯托佛·亚历山大` 在其著作 `《建筑模式语言》` 中首次提出的。本书介绍了城市设计的 " 语言 ",提供了 253 个描述城镇、邻里、住宅、花园、房间及西部构造的模式,而此类 " 语言 " 的基本单元就是模式。后来,`埃里希·伽玛`、 `约翰·弗利赛德斯`、 `拉尔夫·约翰逊` 和 `理查德·赫尔姆` 这四位作者接受了模式的概念。1994 年,他们出版了 `《设计模式: 可复用面向对象软件的基础》` 一书,将设计模式的概念应用到程序开发领域中。
其实有一部分人并没有仔细阅读过设计模式的相关书籍和资料,但依旧可以编写出优秀的代码。这主要是由于在经过众多项目的锤炼和对程序设计的不断追求,从而在多年编程历程上提炼出来的心得体会。而这份经验最终会与设计模式提到的内容几乎一致,同样会要求高内聚、低耦合、可扩展、可复用。你可能也遇到类似的经历,在学习一些框架的源码时,发现它里的某些设计和你在做开发时一样。
为软件开发中相同表征的问题,抽象出的可重复利用的解决方案。
<!-- more -->
## 一、设计模式或者说面向对象的本质是啥?
1. 设计模式往往解决的不是程序运行的效率,因为无论怎样的类或者方法之间的关系,跑起来都是一样的。当然单例、享元等可以节省内存或时间。设计模式更多优化的是程序员开发的效率,通过解耦的方式降低程序的复杂度,抑制熵增。使得本来需要 5 天开发,现在可能需要 3 天就够了。 "the machine does not care, I care!"
2. Design patterns are repeatable, template-based approaches that facilitate developers' productive collaboration across several projects. 记得之前面试顺丰的时候,面试官也认为设计模式的掌握优先级是最高的,因为这是程序员之间的共同语言,能够降低沟通的成本。
## 二、设计模式或者面向对象的原则是啥?
1. 迪米特法则/最少知识原则
1. 最少依赖,一个类中依赖的其他类要尽量少
2. 分层设计 比如 controller service dao
2. 合成/聚合复用原则
- 成员变量实现复用,优先于继承实现复用,本质是:依赖注入的组装优于内部创建对象
3. 继承:里氏代换原则、单一职责原则
- 继承是为了代码复用,实现开闭是利用多态的默认搜索功能去扩展
- 里氏的意思是,要多态的时候父类一定是抽象的空的,如果有具体的功能就会改变父类,导致一些场景把父类换成子类后就不能用了
- 单一的意思是,一个类只负责一个领域的职责
4. 实现:接口隔离原则
5. 开闭原则
6. 依赖倒转
## 三、各对应哪些场景,是哪些现实世界的抽象?
不需要特别学院派,一定把各种模式,比如工厂模式、建造者模式分得那么清楚。更重要的是每个模式对应了什么痛点、什么场景,为什么这么设计,能解决什么问题。了解了这些最本质的东西,就可以灵活应用,甚至可以混用各种模式创造出新的模式,来解决特定场景的问题。
### 创建型:简化对象的创建过程
[工厂模式](工厂模式.md) 华为全家桶、苹果全家桶
[单例模式](单例模式.md) 一个市只需要一家警察局
[建造者模式](建造者模式.md) 一个乐高就需要几千个零件
[原型模式](原型模式.md) 成员变量维度的复用,复制报价
### 类间 - 结构型:field 复用比 extends 复用更灵活
[享元模式](享元模式.md) 对象维度的复用,字符串池
[门面模式](门面模式.md) 事前筹划,用统一的 Monitor 门面,防止以后替换别的 monitor 实现
[组合模式](组合模式.md) 可以抽象为多叉树的对象
### Wrapper 型模式,下边四个实现原理都是聚合
[代理模式](代理模式.md) 主要目的是 AOP 一些非功能性的需求,而非*核心业务功能* 加强,这是它跟装饰器模式最大的不同。
[桥接模式](桥接模式.md) 两个 channel 发四种类型的消息,类的双维度扩展

[装饰器模式](装饰器模式.md) 核心业务功能加强 + 嵌套使用
[适配器模式](适配器模式.md) 事后补救,适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口。
### 方法间/动作间 - 行为型:解耦动作 A 和动作 B 的黏连,不管是前后依赖,还是平行选择,都要解耦
[模版模式](模版模式.md) 多个行为之间有一些相同的套路

[状态模式](状态模式.md) 用查表法来实现有限状态机的状态转移
[命令模式](命令模式.md) 把函数当作变量传递来传递去,策略模式不同策略是平行的,命令模式不同策略是迥异的
[策略模式](策略模式.md) 简单策略模式用枚举

[观察者模式](观察者模式.md) 核心就是动作之间的 attach

[责任链模式](责任链模式.md) 按时间顺序把大动作拆成小动作

[迭代器模式](迭代器模式.md) 集合的底层数据结构可能不同
[访问者模式](访问者模式.md)
[备忘录模式](备忘录模式.md) 备忘录模式常用于需要保存对象历史状态以实现撤销(undo)、回滚(rollback)等功能的场景,例如:
- 文本编辑器的撤销操作
- 游戏存档
- 事务的回滚等
[解释器模式](解释器模式.md) 从表意的字符串中读取出运算逻辑
[中介模式](中介模式.md) 一堆微服务中,注册中心可以理解为广义的中介模式,防止各个服务间错综复杂的调用
## 参考
[设计模式之美 (geekbang.org)](https://time.geekbang.org/column/intro/100039001?utm_campaign=geektime_search&utm_content=geektime_search&utm_medium=geektime_search&utm_source=geektime_search&utm_term=geektime_search&tab=catalog)