基于BREW的松耦合设计再探

来源:互联网 发布:软件培训的英语翻译 编辑:程序博客网 时间:2024/05/21 17:13

 

基于BREW的松耦合设计再探

毛晓冬 2007-10-23

一、       概述:

承接上篇《基于BREW的松耦合设计初探》,本文介绍如何利用BREWINotifier机制解耦应用间的通信。

本文借用的例子是IDLE通知的实现。尽管关于利用INotifier机制实现IDLE通知的阐述我先前的相关文档中已经有涉及,但本文更侧重的是,在需求变化的情况下,如何由原有的设计一步步重构到最终的设计,所以注重的是方案的演化过程,而不是最终的方案本身,以此突出解耦设计的重要性和优越性。

 

二、       需求:

先看下我们的基本需求:当系统退回IDLE,或者离开IDLE状态时,必须告知某些对象(App),以便它们有机会控制自己的行为。

对此需求,一个典型的实例就是,当手机回IDLE时,如果有待下载的MMS,则MMS App自动启动并下载之。

 

三、       第一个设计:

我们首先想到的设计,可能就如下面的框图:

 

 

 

 

看,多简单,够直接吧!!

但是,我们马上就会看到它的致命弱点,究其原因,就是因为IDLE App与具体接收通知的应用间紧耦合,在编译期绑定了一对多的关系,而不是在运行期。

 

四、       出现了什么问题:

我们看看当需求变化时发生了什么?

 

Browser App:我也对IDLE的通知感兴趣了,也通知我吧!

Email App:也加我一个吧!

此时的框图变成什么样了?

 

 

 

 

IDLE App:糟糕!!每加入一个目标App,我都需要更改代码。天晓得将来何时还会再加入新的App

不仅如此,如果MMS App只是想在启动后才收到通知,Browser App任何时刻都想收到通知,Email App有点变态,只想当用户按了某个按钮后才收到通知(我喜欢,你管的着?!)

怎么办?!!

IDLE App:拜托,我能通知你们已经很不错了,别不知足,还奢望特别服务!!

MMS/Browser/Email App:我想安静的时候,就不愿被人打扰,如果这点我都不能作决定,那我宁愿不要你的通知!!

IDLE App:唉!!!!!

这是怎么回事,为何IDLE App这么不堪重负(需求的变化)那。我相信我们已经想到了我们心目中的理想的IDLE App,她应该是:

无需了解任何具体的应用(依赖者),即不和任何的具体应用绑定,进而可以向任意多的应用发出通知,接受通知者可以使用注册/取消的方式自由的控制自己是否想被“打扰”。

可这是我们的目标,通向该目标的途径(实现的方式)又何在那??

 

五、       大师的指点:

“使用Observer模式吧,它定义了对象间的一对多的依赖,当一个对象改变状态时,它的所有依赖者都可以自动收到通知并更新,依赖者还可以动态的加入/退出依赖者的行列。具体的框图可以看看下面的”模式大师道。

 

 

 

 

 

 

“在BREW中,IModelListener机制和INotifier机制就是典型的Observer模式的再现,去使用它们吧”BREW大师说。

“谢谢大师”我们好像明白了些什么,是时候按照大师的指引去尝试了。

 

六、       重构我们的设计:

该使用INotifier还是IModel那?由于IModelListener机制中,观察者将自己的Callback作为对象向被观察者(IModel)注册,所以,通知是基于Callback的,由于Callback中的ClientContext的有效性和应用的生存期绑定,这使得这种通知机制只能发生在应用运行期,不能满足应用不在运行时也能接受通知的需求。

而基于INotifier的机制中,观察者将自己的CLSID作为对象向被观察者(INotifier对象)注册,所以通知是基于Event的,由于Event不与应用的生存期绑定,即便应用不在运行,BREW依旧会先加载应用的实例,然后再处理该Event,所以这种通知可以发生在任何时刻。

所以,我们应该使用BREWINotifier机制来重构我们的方案,下面是重构后的方案框图:

 

 

 

 

此时,通知的触发者(IDLE App)与通知的接受者之间进行了解耦,所有对观察者(依赖者)的管理,以及具体通知的投递都封装在了INotifier对象中。值得一提的是,这里对于Observable(可接受观察者)的实现绝大部分由BREW内核代劳了。这使得在BREW中使用INotifier机制,即达到了Observer模式的好处(通知的触发者和接受者的一对多关系的解耦),又简化了对Observer模式的实现(观察者的管理,包括注册和取消,以及具体通知的投递,都由BREW内核实现)。

 

当需求变化时,你再也看不到千丝万缕的箭头了,一切都在掌控之中。看看下面的动态变化图吧:

 

 

 

 

 

IDLE App永远只需要Trigger通知即可,而具体的通知发出则由INotifier对象完成(或委派BREW完成),所以IDLE App根本对Design期和运行期的观察者的变化一无所知,也无需知道!

 

七、       总结:

如果应用间的通信存在一对多的关系,且这种关系在以后(设计期)或者运行期会发生变化,那么我们需要封装这种变化,以使得一对多的关系解耦。此时,根据需求,我们可以使用BREWINotifier或者IModel机制封装出一个ObservableIModel机制更多的是用于接口和应用(接口)间的一对多关系的解耦。

 

八、       附:

INotifier方式实现IDLE的通知,在BREW3.1.5中已经存在了一个标准接口,INativeNotifier用于此目的,相应的SDK中的头文件是AEENativeNotifier.h,其Reference CodeOEMNativeNotifier.c中,参考代码中已经完全实现了该NotifierOEM唯一需要作的是,在Native IDLE状态发生变化时,调用其对外的方法OEMNativeNotifierClass_Notify即可,OEMNativeNotifierClass_Notify会自动的触发通知并委派BREW内核发出。