JAVA 设计模式总结

Catalogue
  1. 1 UML 类图
  2. 2 六大设计原则
  3. 3 设计模式详解
    1. 3.1 什么是设计模式
    2. 3.2 设计模式的三个分类
    3. 3.3 24种设计模式
      1. 3.3.1 单例模式
      2. 3.3.2 简单工厂模式
      3. 3.3.3 工厂方法模式
      4. 3.3.4 抽象工厂模式
      5. 3.3.5 建造者模式
      6. 3.3.6 原型模式
      7. 3.3.7 适配器模式
      8. 3.3.8 组合(合成)模式
      9. 3.3.9 装饰模式
      10. 3.3.10 代理模式
      11. 3.3.11 亨元模式
      12. 3.3.12 外观(门面)模式
      13. 3.3.13 桥接(桥梁)模式
      14. 3.3.14 模板(模板方法)模式
      15. 3.3.15 解释器模式
      16. 3.3.16 策略模式
      17. 3.3.17 状态模式
      18. 3.3.18 观察者模式
      19. 3.3.19 命令模式
      20. 3.3.20 备忘录模式
      21. 3.3.21 迭代器(迭代子)模式
      22. 3.3.22 访问者模式
      23. 3.3.23 责任链模式
      24. 3.3.24 中介者(调停者)模式

笔者一直想对设计模式做一个全面的学习,这次疫情期间在家的时间多了,所以决定基于网络上的优秀文章把这一块知识好好学习整理一下,原文链接会在具体引用处标注。

1 UML 类图

原文链接>>

2 六大设计原则

原文链接>>

对于上面参考文章中所提的”高内聚,低耦合”原则,到底什么是内聚,什么是耦合呢?
1、耦合
耦合主要描述模块之间的关系。耦合模块之间存在依赖, 导致改动可能会互相影响, 关系越紧密, 耦合越强, 模块独立性越差。
比如模块A直接操作了模块B中数据, 则视为强耦合, 若A只是通过数据与模块B交互, 则视为弱耦合。独立的模块便于扩展, 维护, 写单元测试, 如果模块之间重重依赖, 会极大降低开发效率。

2、内聚
内聚主要描述模块内部。模块内部的元素, 关联性越强, 则内聚越高, 模块单一性更强。
一个模块应当尽可能独立完成某个功能, 如果有各种场景需要被引入到当前模块, 代码质量将变得非常脆弱, 这种情况建议拆分为多个模块.低内聚的模块代码, 不管是维护, 扩展还是重构都相当麻烦, 难以下手。

注意:
模块的粒度可大可小, 可以是函数, 类, 功能块等等。

3 设计模式详解

此模块前两个部分来源于此文章,第三部分关键点总结也大多来源于此链接。需要注意的是,链接中其余内容不用管。

3.1 什么是设计模式

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现实中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。简单说:
模式:在某些场景下,针对某类问题的某种通用的解决方案。
场景:项目所在的环境
问题:约束条件,项目目标等
解决方案:通用、可复用的设计,解决约束达到目标。

3.2 设计模式的三个分类

创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
结构型模式:把类或对象结合在一起形成一个更大的结构。
行为型模式:类和对象如何交互,及划分责任和算法。
如下图所示:

3.3 24种设计模式

对于下面外链文章所涉及到的 UML 时序图,笔者不是很理解它们的细节表达,不过也不影响对知识概念的理解吧,以后彻底理解了时序图的使用再来复盘。同时,下面的链接文章中有些细节性的小纠正会在其文章的评论区有体现,某些评论对了理解还是有其它辅助作用的。

3.3.1 单例模式

关键点:某个类只能有一个实例,提供一个全局的访问点。
单例模式详解>>
上面链接中讲到”双重检查加锁”为什么需要 volatile 关键字时没有讲清楚,它并没有提到 volatile 的”有序性”这一特性,实际上这才是”双重检查加锁”场景为什么需要 volatile 的本质。建议参考笔者之前写过的这篇文章来全面了解 volatile 的作用。

3.3.2 简单工厂模式

关键点:一个工厂类根据传入的量决定创建出哪一参种产品类的实例。
简单工厂模式详解>>

3.3.3 工厂方法模式

关键点:定义一个创建对象的接口,让子类决定实例化那个类。
工厂方法模式详解>>

3.3.4 抽象工厂模式

关键点:创建相关对象或者依赖对象的家族,而无需明确指定具体类。
抽象工厂模式详解>>>

3.3.5 建造者模式

关键点:封装一个复杂对象的构建过程,并可以按步骤构造。
建造者模式详解>>>
以上链接在”电子杂志系统”例子的红色字体部分讲到:虽然在这个例子里面各个产品类均有一个共同的接口,但这仅仅是本例子特有的,并不代表建造模式的特点…
我对这一句话的理解是:对于拥有完全不同接口的产品类的创建过程(这也是大多数场景),一种方案是,分别创建产品(Product)、导演者(Director)、抽象建造者(Builder)、具体建造者(WelcomeBuilder和GoodbyeBuilder),也就是用链文中第一个例子分别创建出各个产品。另一种方案是,复杂对象的构建可以使用链文中最后一种方法,笔者更倾向于此方案,因为能简化流程。
总结一下就是,对于链文中第二个例子的多个产品应用共同接口的情况仅仅是个例,作者只是想把这种特殊情况单独拎出来吧,我们还是要把关注点放在大多数场景的解决方案上来,即第一种方案和第三种方案。

3.3.6 原型模式

关键点:通过复制现有的实例来创建新的实例。
原型模式详解>>>

3.3.7 适配器模式

关键点:把一个类的接口变换成客户端所期待的另一种接口。
适配器模式详解>>>

3.3.8 组合(合成)模式

关键点:将对象组合成树形结构以表示“部分-整体”的层次结构。
合成模式详解>>>

3.3.9 装饰模式

关键点:动态的给对象添加新的功能,是继承关系的一个替代方案。
装饰模式详解>>>

3.3.10 代理模式

关键点:为其他对象提供一个代理以便控制这个对象的访问。
代理模式详解>>>

3.3.11 亨元模式

关键点:通过共享技术来有效的支持大量细粒度的对象。
亨元模式>>>

3.3.12 外观(门面)模式

关键点:门面模式提供一个高层次的接口,使得子系统更易于使用。
门面模式详解>>>

3.3.13 桥接(桥梁)模式

关键点:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
桥梁模式详解>>>
~关于JDBC驱动器的例子没看懂。以后在来复盘。~

3.3.14 模板(模板方法)模式

关键点:定义一个算法结构,而将一些步骤延迟到子类实现。
模板方法模式详解>>>

3.3.15 解释器模式

关键点:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
解释器模式详解>>>

3.3.16 策略模式

关键点:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
策略模式详解>>>

3.3.17 状态模式

关键点:允许一个对象在其对象内部状态改变时改变它的行为。
状态模式详解>>>

3.3.18 观察者模式

关键点:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
观察者模式详解>>>

3.3.19 命令模式

关键点:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
命令模式详解>>>

3.3.20 备忘录模式

关键点:在不破坏封装的前提下,保持对象的内部状态。
备忘录模式详解>>>

3.3.21 迭代器(迭代子)模式

关键点:顺序地访问一个聚集中的元素而不必暴露聚集的内部表象。
迭代子模式详解>>>

3.3.22 访问者模式

关键点:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
访问者模式详解>>>

3.3.23 责任链模式

关键点:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
责任链模式详解>>>

3.3.24 中介者(调停者)模式

关键点:用一个中介对象来封装一系列的对象交互。
调停者模式详解>>>