笔者一直想对设计模式做一个全面的学习,这次疫情期间在家的时间多了,所以决定基于网络上的优秀文章把这一块知识好好学习整理一下,原文链接会在具体引用处标注。
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 中介者(调停者)模式
关键点:用一个中介对象来封装一系列的对象交互。
调停者模式详解>>>