插件系统[4]·关系模式-万能观察者

来源:互联网 发布:数据分析的发展历程 编辑:程序博客网 时间:2024/05/16 10:11

插件的独立性与插件之间的依赖关系是插件框架必须解决的问题。

其中独立性与插件的划分粒度相关,将每一个插件实现为一个dll,从物理层面强制保证了插件的独立性。插件之间的依赖关系是要解决的更加复杂的一个问题。

一、观察者模式

我们将系统分割成一系列相互协作的类,常见的会有一个副作用:需要维护相关对象间的一致性。但我们并不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性。(引用自GoF的《设计模式》)


在Subject的某一个固定时刻,将会调用Observer的Update通知观察者。

二、观察者的进化历程

2.1 增加观察兴趣

上面只是考虑到了一种简单的情况,即相互协作的类之间只会有一种交互。但通常在系统中交互的场景并不只是一种。也就是说观察者类型(接口)并不仅仅是一种,而是两种或多种。

这时候我们不能简单地在Subject中存储一个FObservers列表了事,也许要存上多个。如下图:


或者我们专门用一个观察者列表的管理器来管理这么多的观察者接口:


2.2 推模型VS拉模型

从上面的说明上可以看到,将观察者需要的信息通过Update方法传给观察者,这是“推”模式。另外还有一种情况是由观察者收到Update通知后,主动从目标取信息,这是“拉模式”。推模式和拉模式表明了触发更新的角色。

2.3 观察列表的统一管理

如果需要观察者触发更新,那么需要在观察者中保存对目标的引用,让观察者能在适当的时候调用Notify方法。同时,在一个系统中,目标和观察者都是相对的概念,对于一个模块来说,在有的应用中作为目标存在,另外一些应用中又是作为观察者存在。
经过分析后,可以将观察者管理器统一处理,作为一个目标与观察者的注册中心。

三、通用关系——主体、客体

3.1 关系管理器

现在的观察者已经和原有的观察者模式有了比较大的区别,观察者的注册中心存储的并不仅仅是观察者列表,而是“目标-观察者”对,通过一个目标可以找到若干个对应的观察者。如下图所示:


关系是对象之间交互的描述。在我们的系统中,对象指的是接口。任何一个模块都可以找到和自己关联的某一类接口,模块之间通过接口交互。注册中心的实质是管理模块之间的交互,作为一个关系管理器存在。

在一个“目标-观察者”交互中,目标触发交互过程,观察者接受信息。可以将一次交互分为“主体-关系-客体”三个部分,等同于语法中的“主谓宾”结构,至于那个模块是主体,那个模块是客体,那就要看在关系管理器中的定义。

3.2 关系的注册

在观察者模式中,我们需要调用Attach与Detach来注册、取消观察者。将目标与观察者的概念进一步抽象成对象与对象之间的关系后,我们不再需要调用目标的Attach与Detach方法了。一切都是关系管理器的职责。

在关系管理器中提供Register与Unregister来完成类似的功能,通过FindRelated来查找观察者列表,这样可以实现观察者模式中的功能,并且可以方便地扩充观察点。

四、应用场景

插件系统中要解决的两个重要问题:独立性、依赖性。这两个特性有着矛盾的地方,不过通过接口可以有效地实现模块之间的隔离。当一个系统中只有十几个模块的时候,交互不是大的问题,但当系统中存在上百个模块时,就需要对模块之间的交互进行管理。

关系模式是一种对象交互模式,上面描述的关系模式是在关系模式的基础上的一种发展,比较适合在插件系统中管理插件之间的交互关系。并且这些关系是可定制的。具体的定制方式和实际的业务有很大关系,这里不再细说。

目前已经在插件系统中应用关系模式,但我认为这个思想是可以借鉴到其他的系统中的。 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1400266


原创粉丝点击