概要
结构型设计模式主要是用于处理类和对象的组合,如何将类与对象更好的组合起来。 我们常用组合类与对象的手段无非继承与多态。不恰当的使用继承会带来类爆炸与结构不稳定的风险,而结构型设计模式 就是教会我们一些手法,让我们的类与对象组合起来更好。 一共包括七种,分别是适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式。 其中适配器模式,装饰模式,代理模式无论日常开发还是源码中使用都是比较常见的模式。 这七种模式思想与功能各有特点(特别是享元模式与外观模式),无论从类行为方面还是代码层面,我没有找到好的角度去把它们分类。 如果非要分的话,可以从代码层面分为组合做法与非组合做法。 组合做法,既将工作委派给其他对象。适配器模式,桥接模式,组合模式,装饰模式,代理模式中的静态代理在代码实现时都是这种做法。
这七种模式整体来讲学习难度并不大。
| 名称 | 场景 | 优点 | 缺点 | 核心思想 | 生活中例子 | 代码例子 |
|---|---|---|---|---|---|---|
| 适配器模式 | 系统中某个接口不满足需求,需要转换为另外一个接口 | 灵活性强,可以让两个不相关的类一起运行 | 过多的适配器类会让代码凌乱 | 1.两个不相关的类建立连接(A假装B)2.设计除臭剂(出现的原因就是一开始设计没完全考虑好,当然这无可厚非,但如果出现过多,该反思一下设计是否合理) | 转接头 | 适配器模式 |
| 桥接模式 | 系统中一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展 | 优秀的扩展能力 | 让代码更复杂 | 剥离变化维度,选取主体。其余变化维度以抽象类的形式持有,防止类爆炸。 | 分类型与颜色的画笔 | 桥接模式 |
| 组合模式 | 系统中有树一样的层级关系(文件系统,组织架构) | 1.开闭原则,增加节点便捷 2.节点统一对待 | 很难精确地识别到场景以及提取公共接口,稍有不当代码很难理解 | 当存在树形结构时,将叶子节点和非叶子节点统一对待,但对非叶子节点的操作都委派给叶子节点 | 公司组织结构 | 组合模式 |
| 装饰模式 | 系统中需要动态扩展对象功能,发现继承不可行或者类爆炸时 | 装饰类和被装饰类可以独立发展,不会相互耦合 | 如果修饰类较多,如果出错,需要一层一层剥离定位问题 | 需要动态扩展对象功能,发现继承不可行或者类爆炸时 | 普通煎饼与豪华煎饼 | 装饰者模式 |
| 外观模式 | 系统中需要调用一组接口时 | 迪米特法则 | 没有任何的抽象和继承,单纯的组合。不满足开闭原则 | 提供了一个统一的接口,用来访问子系统中的一群接口 | 体检机构的接待员 | 门面模式 |
| 享元模式 | 系统中某个对象大量存在,并且这些对象只有几类(部分相同) | 减少对象创建,减少内存使用 | 很难精确地识别到共享对象(部分相同,变的类型有限) | 缓存思想。对象多,但只有几类,可以狭隘理解为N个单例模式的集合。 | 围棋(只有坐标不同) | 享元模式 |
| 代理模式 | 系统中需要在某个对象前后做一些事情 | 扩展性强 | 1.代码更复杂 2.可能增加服务相应时间 | 控制:使用代理类来控制源对象。通常自行管理其服务对象的生命周期 | 媒婆 | 代理模式 |
模式之间的差异与联系
- 桥接模式通常会于开发前期进行设计, 使你能够将程序的各个部分独立开来以便开发。 另一方面, 适配器模式通常在已有程序中使用, 让相互不兼容的类能很好地合作。
- 适配器可以对已有对象的接口进行修改, 装饰模式则能在不改变对象接口的前提下强化对象功能。 此外, 装饰还支持递归组合, 适配器则无法实现。
- 桥接、 状态模式和策略模式 (在某种程度上包括适配器) 模式的接口非常相似。 实际上, 它们都基于组合模式——即将工作委派给其他对象
- 装饰可让你更改对象的外表, 策略模式则让你能够改变其本质。
学习建议
必学
- 适配器模式
- 组合模式
- 装饰模式
- 外观模式
- 代理模式
选学
- 桥接模式
- 享元模式