文章首发于公众号「架构师指南」及个人博客 shuyi.tech,欢迎关注访问。

学习过设计模式的都知道,设计模式分为三大类,分别是:创建型、结构型、行为型。但为什么它们这么分呢?某个设计模式为啥就属于结构型,而不属于行为型呢?创建型、结构型、行为型它们到底有什么不同呢?今天就来聊一聊我的理解。

创建型模式

创建型模式,顾名思义就是用来创建对象的。 创建型模式包含的五个设计模式,分别是:

创建型设计模式

从它们的作用来看,它们全部都是创建新对象相关的模式。

工厂方法模式、抽象工厂模式、建造者模式都是创建新对象,可以屏蔽创建对象的细节。原型模式是进行对象克隆,也算是新对象创建。单例模式是控制只能创建单个对象,其也包含了对象的创建,因此也算是创建型模式。

结构型模式

结构型模式,就是介绍如何将对象和类组装成较大的结构,并同时保持结构的灵活和高效。结构型模式把一个个对象结合在一起,就像积木搭建起来一样,有一种结构化的感觉。 结构型模式包含 7 个设计模式,分别是:

结构型模式

适配器模式 指的是可以让不兼容的对象能够合作,通常情况是有一个适配器类实现了多个接口,从而在接口方法中写入特定逻辑去做兼容适配。这里的结构体现在对于两种对象的兼容,通过兼容将新老对象组合起来了。

桥梁模式 其实就是把固定的和变化的分离开来,使用组合的方式去实现。将固定的放在原地不动,而变化的则抽离出去作为一个新的类,再通过组合的形式被老的类引用。这里的结构体现在旧类对新类的引用,它们之间变成了一种结构型关系。

组合模式 就是多个结构组合起来,形成一个更复杂的结构。组合模式更多是一种数据结构的呈现,而不能说是一种设计模式。但从广义的设计模式定义来看,将组合模式说成是一种设计模式,也没有错。

大家会发现组合模式和桥梁模式非常像,其实这两者之间并没有太大的差别,甚至是说基本一样。桥梁模式与组合模式,其实都是基于组合这种关系,不同的对象组合起来形成更大的结构体。桥梁模式是基于组合模式的。

装饰模式 指的是使用很多其他类对原有类进行功能增强,就像美颜APP一样,我们使用很多滤镜对照片进行功能增强。这一个个的滤镜就嵌套在原有的照片上,就像一个个功能增强类嵌套在原有的基础类上一样。装饰模式的结构性就体现在这种嵌套关系上,一层层的嵌套组成了一种结构。

门面模式 指的是提供一个全新的接口层,将子系统复杂的接口内容屏蔽了。则像是肯德基的前台一样,帮你把一切复杂的东西屏蔽了。你不需要关心汉堡怎么做,奥尔良鸡翅怎么做。你只需要告诉前台要吃什么,它就会把汉堡、鸡翅等东西做好了拿给你。

在门面模式中,我们在使用方与子系统之间插入了一层接口层,去屏蔽复杂的内部细节。就像是肯德基的前台,帮我们屏蔽了内部食物的制作细节一样。门面模式的结构就体现在我们插入的这一层「门面」上,它将使用方与子系统连接起来,让使用更方便了!

享元模式 指的是共享同一个元素,是一种节省内存的设计模式,其实就类似我们的池技术。与其他对象复杂的结构相比,我都不觉得享元模式是一种设计模式,而只是一种思想而已。但如果严格地从设计模式的定义来讲的话,那其实也可以算是。

在享元模式中,我们会新增一个类去保存元素的映射池。而这个新增的类就相当于是一个新增的对象,通过组合的形式去节省内存的消耗。享元模式的结构性更多是通过组合的形式体现的。

代理模式 其实就是一个代理卡在买卖双方中间,做一些流程上的控制。代理模式的结构性就体现在多了一个代理类,卡在「买卖双方」中间,这种结构特征不言而喻。

从上面我们的描述来看,我们可以知道结构型模式很多时候,就是两者对象之间有一个对象挡在中间,例如:适配器模式、门面模式、代理模式。要不就是通过某些关系组合在一起,例如:桥梁模式、组合模式、装饰模式、享元模式。

行为型模式

要理解行为型模式,就要重点留意行为。虽然行为型模式有些点与结构型模式类似,但是其最大的特点是行为,是这个动起来的东西。

我们举个例子:为什么中介者模式属于行为型模式,而代理模式属于结构型模式?

中介者模式听起来与代理模式很像,但中介者模式说的是做多个对象之间的协调工作,协调他们的行动!看到了吗?协调他们的行动,才是中介者模式的核心,所以说中介者模式才是行为型模式。而代理模式,则不会有那么多个对象之间复杂的关系,其侧重于对被代理对象的控制。其重点不在于复杂的对象关系,不在于协调多个对象的工作,而在于单个对象的控制,代理就像卡在两者中间的一个结构一样。

有些朋友要说了,那其实代理模式也有对代理对象的控制这一行为啊,为什么不能算是行为型模式呢?代理模式确实有对代理对象控制这一行为,但这里要强调的是重点这个词。这里并不是说代理模式就没有行为,而是说代理模式的行为比起结构性少,并且不是重点。而中介者模式肯定也有结构性的东西,但它诞生的目的就是为了协调多个子系统的复杂调用关系,协调关系才是中介者模式的重点。

行为型模式有 10 个设计模式,分别是:

责任链模式,是一个个对象组合起来的对象链。 其请求会从链头传到链尾,每个对象可以判断其是否返回或传递到下一个对象。其侧重于是否返回或传递下去,重点是在这个行为的处理。所以责任链模式才叫行为型模式。

命令模式,是把要做的事情抽象起来,形成一个命令。 后续要做这个事情的时候,我直接给一个命令你就知道我要做什么了。为什么要这么做呢?因为变化!如果我们的命令有很多个,那么每次我修改一个命令,我就要修改发出命令和执行命令两个地方。

但实际上发出命令的动作是不会变的,变化的只是执行命令的地方。于是为了隔离变化,那么我们将执行命令这块分离出去。那么发出命令与执行命令怎么沟通呢?答案是通过命令!这个其实就类似于餐厅前台与后厨的沟通。餐厅前台给的做菜单就是一个命令,后厨拿到这个命令之后就去执行。

可以看到在命令模式里,其核心是拿到命令去执行,它们之间也是一个行动的概念,因此命令模式也才归属于行为型模式。

迭代器模式,其实就是实现了集合所有元素的遍历,让你使用的时候不需要关心它底层的数据结构。 其重点在于对集合元素的遍历这个行为,所以归属于行为型模式。在现在基本上只存在于源码、框架中,实际工作用到的很少了。

中介者模式,前面说过了其侧重于对多个对象之间的协调。 其重点在于协调这个事情,所以其归属于行为型模式。

备忘录模式,就是在某个时候把东西记下来,避免忘记了。 在编程上,其实就是在某个时刻将对象的信息记录保存下来,从而在另一个时候可以恢复。其重点在于,其实现上会有一个专门的类来帮你记录下信息,所以归属于行为型模式。

观察者模式,从其名字可以知道有些人盯着你,需要知道你的动向,其实就是发布订阅模式。 其重点在于观察这个动作,观察之后将这个事情传递出去,你看到这些都是一个个的动作,因此归属于行为型模式。

状态模式,就是更为方便地控制状态。 如果一个事物的状态转换比较复杂,那么可以将其状态抽离出来,单独作为一个类。这样其状态的变化就可以更好地控制,也分离了变化。这个就是状态模式的应用。从名字来看,我们会觉得它应该是结构型模式,即包含某状态嘛。但实际上,其侧重于对于状态更好地控制,所以归属于行为型模式。

策略模式,其实就是对于不同的东西,用不同的处理方式。 一般情况下,单个具体的策略就是一个类,而这些类都会实现这些策略共有的一个接口。其重点在于不同东西,不同的处理方式。重点在于处理方式的不同,所以归属于行为型模式。

模板方法模式。 这里有两个词,即:模板、方法。模板指的是一套固定的东西,其实就是固定的额算法。方法,表示这个模板是存放在方法上的。所以叫模板方法。简单地说,模板方法其实就是父类定义了接口类的一些共有算法。子类不能改变这个算法流程,只能做有限的扩展。所以模板方法的重点是父类控制了一整套行为流程,其核心在于有一套固定了的算法行为,所以叫行为型模式。

访问者模式。 访问,即当你当成了外人,不想你随便动。你要什么,我弄好之后给你(调用你的方法)。其定义的还是访问者与被访问者之间应该如何沟通的问题,所以归属于行为型模式。

总结

为什么要费尽周折从分类上去说这些设计模式呢?因为这样能更好地理解设计模式。 一个设计模式能归属于某个分类,我相信并不是巧合,肯定是因为其特性是符合这个分类的,不然不可能随便地进行分类。

所以我们去研究为什么这个模式归属于这个分类,可以更好地理解这个模式的本质,使得我们对这些设计模式有更好的理解。与此同时,我们在研究的过程也是深入理解的过程,也是对比的过程,不断加深我们的理解与认知。

但囿于个人对于知识的理解程度不同,可能我在某些模式上的理解也并不是很透彻,有些解释可能会有点牵强,甚至望文生义。所以大家看的时候还是得批判性地读。如果有更好的解释,可以留言告诉我,我们一起深入讨论。


陈树义
6 声望2 粉丝