软件体系结构【3】 基于事件的软件系统结构

这一章有一些新的概念,我尽量说得简洁一些。

事件系统是一个过程间使用隐式调用的系统

那么问题来了。

第一,什么是过程?过程是程序设计中的一个模块,通过调用命令运行。

第二,什么是隐式调用?说隐式当然是因为有显示调用,那么什么是显式调用呢?显示调用中调用者必须知道被调用者的类名、构造方法(包括参数)与要调用的方法(包括参数)。而在隐式调用中,一个事件将会自动的调用某些过程。

是不是非常神奇!

将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。事件驱动风格就是解决这类的耦合关系的。

在事件驱动的软件系统结构中,构件不直接调用一个过程,而是触发或广播一个或多个事件。广播机制是什么?就是在有一些操作完成以后会发送广播,比如说发出一条短信,或打出一个电话,如果某个程序在当前事件中注册了,那它就会接收这个广播,从而做相应的处理。这样,系统中的其它构件中的过程在一个或多个事件中注册的时候,当一个事件被触发,系统自动调用在这个事件中注册的所有过程,从而一个事件的触发就导致了另一模块中的过程的调用。

在有独立事件分发模块(负责分发和接收事件)的系统中,有两种分发策略,一种是对所有模块发送广播,一种是只对注册事件的模块发送广播。

对于没有独立事件分发模块的系统,每个模块都允许其他模块对它发送的事件感兴趣,同时只能将广播发送给对其感兴趣的模块。

很多系统实现了广播机制,比如Android,就可以很容易的通过接口来处理事件。如调用sendBroadcast()发送普通广播,调用sendOrderedBroadcast()发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。建议大家可以试试,可以做一些很有趣的小应用比如黑名单拦截~

 

说了这么多,再来个栗子🌰吧。

观察者模式。非常经典,用了都说好👍。

类图

分析一下

可以看出,主要思想就是让主题保持一个动态列表,记录已经注册的观察者(一个主题可能拥有多个观察者)。需要注意的一点是,观察者必须注册自己,才可以保证程序正常运行。

大家看到了第一个类图里面有“拉模型”的注解。因为当目标通知观察者的时候是全部都通知,但是现在这个需求是不同的情况来让不同的人处理,怎么办呢?解决的方式通常有两种,一种是目标可以通知,但是观察者不做任何操作,将观察者所需数据全部推给观察者, 例如,update(Object  a);另外一种是在目标里面进行判断,干脆就不通知了,主题提供接口,供观察者访问,例如update(Observable obs)。推拉实现方式各有千秋,这里选择后面一种方式来示例,这种方式能够统一逻辑控制,并进行观察者的统一分派,有利于业务控制和今后的扩展。

同时观察者模式有许多变形,朴素的观察者模式中,所有的观察者都是一样的,目标会一视同仁的对待。不过我们也可以通过在目标里面进行控制,实现有区别对待观察者,比如某些状态变化,只需要通知部分观察者。

观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。同时,依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。所以,当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时;或者一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用时,可以考虑观察者模式的应用。

 

好啦,到此为止吧。

 

posted on 2016-10-10 23:39  HoneyCat  阅读(1395)  评论(0编辑  收藏  举报

导航