go语言实现观察者模式 go 观察者模式

观察者模式订单状态流转

观察者模式还是非常常用的,常见于基于zookeeper进行分布式系统之间的协调工作,比如分布式锁的注册以及监听是否释放。还有就是两个系统之间如果做了异步的处理,那么如果A系统发送异步请求给了B系统,但是要得到B系统的一个状态改变的消息,可以采用观察者模式。

创新互联建站主营长安网站建设的网络公司,主营网站建设方案,app软件开发,长安h5小程序定制开发搭建,长安网站营销推广欢迎长安等地区企业咨询

使用场景

在Zookeeper中的监听回调机制,以及分布式锁,都是使用了观察者模式。

基于zookeeper去做分布式锁

(1)系统A尝试获取zookeeper上的一个锁,获取到了

(2)系统B尝试获取zookeeper上的一个锁,被系统A给锁了,没有获取到锁,此时系统B在zookeeper上可以注册一个监听器(观察者)

(3)系统A一旦将锁给释放了,zookeeper感受到锁被释放了,就会立即通知系统B注册的那个监听器

(4)系统B就立即被通知到了,系统A释放了锁,系统B可以重新尝试在zookeeper上加锁

电商系统里,也有这种场景,如果两个系统之间走了异步请求,那么可以基于上面那种观察者模式现在一个进程内实现监听,以后拆分微服务分布式架构了,可以改成基于zookeeper来做分布式协调。

系统A发送了一条消息到内存队列,系统B获取了消息开始执行操作

但是系统A需要知道系统B的一个执行的结果如何,

此时系统A需要注册一个观察者到系统B上去,系统B执行完了之后,将执行的结果,反过来通知给系统

我们就可以基于观察者模式去做。

观察者模式是什么

官方解释:

观察者模式(有时又被称为发布-订阅Subscribe模式、模型-视图View模式、源-收听者Listener模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。

个人理解:

观察者模式是一种思想,不需要人为的去关注观察者和被观察者之间是怎样联系的,实现了解耦,只需要对象去注册被观察者(Observerable)与观察者(Observer),然后被观察者去添加一个或者多个观察者,当被观察者发生变动就会立即通知所有的观察者,下面让我们来看看是怎样实现这个功能的。

被观察者首先通过addObserver(Observer o)来添加一个观察者,底层代码中会把这个对象o放进一个vector集合中,当然也可以添加多个观察者,当观察者发生变动的时候就会触发

setChanged();

notifyObservers();

这两个方法,然后底层代码中就回去遍历装有观察者的那个vector,然后

for (int i = arrLocal.length-1; i=0; i--)

((Observer)arrLocal[i]).update(this, arg);

调用update方法通知每一个观察者,这样观察者对象中就可以拿到被观察者的相关对象和信息

观察者模式(Observer)的推式与拉式

当我们想订一份报纸,我们先去邮局找到报纸的编号后填写订阅单并缴费。当报社有新报纸发出时,邮局会将我们订阅的报纸发给我们。

为了简单我们去掉邮局环节简化成:报社有新报纸后马上通知用户,这就是观察者。

定义对象间的一对多关系,当一个对象的状态发生变化时,所依赖于它的对象都得到通知并主动更新。 在观察者模式中,多个订阅者成为观察者(Observer),被观察的对象成为目标(Subject)。观察者的UML模型如下:

先定义Subject并写一个ConcreteSubject继承Subject:

再定义一个接口Observer,并写一个ConcreteObserver实现Observer接口:

最后看看主函数方法:

打印出来的结果:

在实现观察者模式的时候,一定要注意触发通知的时机。一般情况下是在完成了状态改变之后触发,因为通知会传递数据,比如在 setSubjectState 时先通知观测者就会发生 错误 。

在观察者模式的实现上,有推模式和拉模式两种方式:

当前上面的实现使用的就是拉模型。通过 (ConcreteSubject)subject 得到具体对象,获得信息。

当然Java本身就有观察者模式的部分实现,分别是 java.util.Observable java.util.Observable 。

下面看一个使用Java自带观察者模式的例子:

新的目标直接继承Java中定义的Observerable:

新的观察者也直接实现Observer接口:

主函数和前面的相似:

打印出结果:

使用Java自带的观察者模式需要注意以下几个问题:

什么是观察者模式`?

观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式。GOF给观察者模式如下定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

在这里先讲一下面向对象设计的一个重要原则——单一职责原则。因此系统的每个对象应该将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。这样在开发中也就带来了诸多的好处:提供了重用性和维护性,也是进行重构的良好的基础。

因此几乎所有的设计模式都是基于这个基本的设计原则来的。观察者模式的起源我觉得应该是在GUI和业务数据的处理上,因为现在绝大多数讲解观察者模式的例子都是这一题材。但是观察者模式的应用决不仅限于此一方面。

下面我们就来看看观察者模式的组成部分。

1)抽象目标角色(Subject):目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。

2)抽象观察者角色(Observer):为那些在目标发生改变时需要获得通知的对象定义一个更新接口。抽象观察者角色主要由抽象类或者接口来实现。

3)具体目标角色(ConcreteSubject):将有关状态存入各个ConcreteObserver对象。当它的状态发生改变时,向它的各个观察者发出通知。

4)具体观察者角色(ConcreteObserver):存储有关状态,这些状态应与目标的状态保持一致。实现Observer的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向ConcreteSubject对象的引用。

观察者模式解析

定义 :对象间的一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于他的对象都会得到通知,并自动更新。

交互对象之间松耦合

1)观察者定义了对象之间一对多的关系

2)被观察者用一个共同的接口来更新观察者

3)观察者和被观察者用松耦合方式结合,被观察者不知道观察者的细节,只知道观察者实现了观察者接口

优点:

1)观察者与被观察者抽象耦合,容易扩展;

2)建立了一套触发机制。

缺点:

1)循环依赖会导致系统崩溃;

2)观察者太多会浪费时间。

1)定义对象之间的一对多依赖关系而不使对象紧密耦合。

2)确保当一个对象改变状态时,自动更新开放数量的从属对象。

3)一个对象应该可以通知开放式数量的其他对象。

观察者模式 vs 发布-订阅模式

观察者模式(Observer)

如何使用 Java8 实现观察者模式?(上)

如何使用 Java8 实现观察者模式?(下)

如何实现Application event,观察者模式

spring 事件为bean 与 bean之间传递消息。一个bean处理完了希望其余一个接着处理.这时我们就需要其余的一个bean监听当前bean所发送的事件.

spring事件使用步骤如下:

1.先自定义事件:你的事件需要继承 ApplicationEvent

2.定义事件监听器: 需要实现 ApplicationListener

3.使用容器对事件进行发布

最后有一个思考 :ApplicationEvent事件执行部分和起一个TaskExecutor去执行 有啥区别吗?反正都是异步。

可以这样实现;

还可以这样实现;

我的思考:ApplicationEvent是观察者设计模式,这种设计模式使得主题和观察者之间的耦合度降低,松耦合是面向对象设计中很重要的一个原则,最终也是使用@Async来实现异步。而TaskExecutor则是启动一个线程池任务异步执行任务,两者效果一样,但原理不同。

通过我的思考,又带来一个疑问:那观察者模式是不是就是我们MQ中的发布订阅模式呢?只不过观察者模式是进程内的,而MQ是跨进程的?就这唯一的区别吗?

经过一些资料的查阅:大多数地方观察者模式 约等于 发布订阅模式,但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会。

所以说观察者模式是小米加步枪,发布订阅模式是95式自动步枪,是它的进化版!


标题名称:go语言实现观察者模式 go 观察者模式
标题链接:http://hbruida.cn/article/dodsggc.html