写点什么

观察者模式

用户头像
soolaugust
关注
发布于: 2020 年 12 月 25 日
观察者模式

最近由于项目原因,重启拾起了Android开发,发现现在Android多了很多新的特性,特别是LiveData,可以在数据发生变动时更新活跃的观察者,这个就是观察者模式的完美体现,所以今天我们来谈一下观察者模式。



1_sieWEKvfUKPgOWIcKSbN1A.png



我们在前端和Android等类前端项目开发时,会发现大量的listener和broadcast的使用,因为他们都面临着一种使用场景,也就是事件触发的时间不可控,可能是由用户手动触发或者特定时间的触发,而服务需要对这种事件进行反映。当然在类前端项目中,UI线程一般是单独的线程,这就导致其他线程如果需要更新UI,必须将自己的事件传输到UI线程。这些都是观察者模式的使用场景,那么我们今天就讨论一下观察者模式和其背后的设计哲学。

设计模式

在讨论观察者模式之前,我们先讨论一下设计模式。

设计模式是什么

一般来说,设计模式是软件设计中为了特定问题而提出的一种解决方案。通常代码中会反复出现一些设计问题,而设计模式就是为了解决这种问题,但是设计模式和特定的方法或者库不同,在实际使用中很难直接套用某个设计模式,而是根据设计模式来实现符合实际需求的解决方案。

另一方面,设计模式和算法很容易混淆,因为两个都是为了解决特定问题。但是算法是明确解决问题所需的一系列步骤,是具体的而且可以直接套用的。而设计模式是一种更高层次的抽象,可以看到最终的效果和相应的功能,但是不能直接套用,需要自己设计具体的实现步骤。

如何设计一种设计模式

设计模式主要是为了解决特定的问题,所以我们在理解或者设计一种设计模式时,首先要明确的就是设计模式面临的问题,然后提供具体的解决方案。也就是以下内容:

  • 意图:简单描述问题和解决方案。

  • 动机:进一步解释问题并说明模式如何来提供解决方案。

  • 结构:主要是解决方案中各个部分和他们之间的关系。

  • 代码实现:因为设计模式具体来说还是为了解决代码问题,最好有相应的代码实现。

设计模式的发展

设计模式的兴起源于一本知名的书 《设计模式: 可复用面向对象软件的基础》,首次将设计模式的概念应用到程序开发中,书中提供了23个设计模式来解决面向对象程序设计中的各种问题。也是我们接下来重点会说明的内容。当然随着程序设计的发展和应用场景的变化,人们设计了更多的设计模式。不过说到设计模式,还是以这23种为主。

设计模式的错误使用

设计模式只是为了解决具体的问题,所以不应该将其教条化,认为在任何时候都要使用设计模式,或者一定要用什么设计模式,设计模式都有其局限性或者说是适用范围,不适当的使用会使得项目在后期变得难以拓展。同时不是一定要按照推荐的设计来使用设计模式,而是要根据具体的语言或者项目情况来设计所用的设计模式,照搬设计模式会增加项目的复杂度和维护成本。

演示文稿1.jpg



设计模式分类

观察者模式是一种行为型设计模式,行为型设计模式的定义如下:

行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。

听上去很复杂,但是我们可以简单从设计模式的分类上来简单理解,我们一般将设计模式分为三类,除了行为型设计模式,还有创建模式结构模式。这些设计模式关注的点不一样:

  • 创建模式:主要关注对象的创建

  • 结构模式:主要关注对象的组合

  • 行为型设计模式:更关注对象之间的交互。

具体的设计模式和内容参考下图。



image.png



那么这样就好理解了,比如今天我们要说的观察者模式,就是关注观察对象和观察者之间的交互。

观察者模式

观察者模式更为熟悉的名字应该是发布订阅模式。在《设计模式》中的定义是:

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

也就是定义一个对象之间一对多的依赖,当一个对象状态发生改变时,所有依赖的对象都会接收到对象。一般来说,被依赖的对象是被观察者,依赖的对象是观察者。



image



观察者有很多种方式和叫法,而在我看来,观察者的实现有三种方式:推模式,拉模式,中介模式。

推模式

推模式就是被依赖的对象主动把自己的状态更改发送到所有依赖的对象,也就是被观察者持有所有观察者的接受方法并主动推送。应用场景一般是观察者较多,而被观察者较少的情况。这种一般也是最为常见的一种方式,比如前端或者安卓中的各种listener,能够在相关事件发生时,触发各种监听事件。



演示文稿1.jpg



拉模式

拉模式也就是依赖对象主动去拉取自己关注的状态,比如各种状态和日志等监控服务。应用场景一般是被观察者较多,被观察者较少的情况。比如状态监控程序,根据状态提供者注册的服务,来不断轮询各个状态提供者,拉取自己需要的信息。



演示文稿1.jpg



中介模式

事实上中介模式也是设计模式中的一种行为型设计模式,和上面两种并没有什么冲突的地方,而且一般来说也会配合着使用。这里我们主要讲述观察者模式如何和中介模式配合,主要是寻找一个中介者(也称为调解器,注册中心等),用来推送和拉取相关的主题,这进一步将观察者和被观察者进行解耦。在很多微服务和系统设计中都有所体现,比如kafka的日志收集设计,Go语言的channel设计,Android中的broadcast设计...因为这种设计有很多好处:

  1. 降低系统的复杂度和耦合程度,观察者和被观察者只需要和中介者进行通信,这样观察者和被观察者不用依赖对方,同时整个系统对观察者和被观察者的类型也没有进行限制。

  2. 可以动态伸缩观察者,被观察者和中介者。因为完全解耦,可以根据需要进行相应的添加或者删除。比如需要存储更多的状态,那么就添加更多的中介者。

  3. 可以在中介者增加缓存和负载均衡,减少观察者层和被观察者层的压力,以增加系统的抗压能力和稳定性。



演示文稿1.jpg



推荐阅读



发布于: 2020 年 12 月 25 日阅读数: 11
用户头像

soolaugust

关注

公众号:雨夜随笔 2018.09.21 加入

公众号:雨夜随笔

评论

发布
暂无评论
观察者模式