事件机制与消息机制的架构设计区别(一)
公司一个项目中有这样一个情景:这是一个C/S架构的软件,S端采集各类第三方系统数据,传输到C端,然后在C端将数据整合成一个个的业务对象,同时针对各类业务对象,编写了相应的展示UI;用户在二次开发时,根据实际需要将业务对象与展示UI进行匹配,最后形成对第三方系统数据的动态显示。其实说白了就是类组态软件,这个在很多行业都有类似的软件。
在这个场景中,实际上涉及到这样一种需求:要求业务对象的数据变化能够传递到UI对象中,以触发UI对象的展示逻辑,进而形成实时动态数据显示。
在设计C端架构时,针对这个需求,我和同事提出了两种架构设计:
第一种:我的设计
PS:没有VISIO,用VS简单来个类图吧。
EnityManager和UiManager分别是业务对象和UI展示的管理类,Enity和UiModel分别是业务对象和UI展示对象,其中的Values则是对象中的数据列表,ValueObject、Enity、UiModel均继承自BaseObject;EventLinkManager则是数据变化传递管理对象,LinkNode是传递节点。
大致的工作模式是这样的:调用EventLinkManager.LoadEventLink()方法载入数据传递关系,分别去EnityManager和UiManager中搜索Source和TargetObject,然后挂接SourceValueObject的ValueChanged事件回调,在SourceValueObject_ValueChanged方法中获取Source的Value再Set到Target的Value中去。这样,任意一个ValueObject的Value变化触发ValueChanged事件就可以将值传递到另外一个ValueObject中去。这个传递过程完全依赖于事件机制。
当然,我在这里给出的只是一个简化设计,实际考虑的要比这个复杂些,包括线程安全,查找算法,以及引入依赖注入等等。
第二种:同事的设计
PS:同事也给出了他的设计,这是要跟我对掐么?
好吧,至少我们对业务对象和UI展示部分的设计是一致的,差别在哪里呢?是的,差别在于如何将业务对象的值变化传递到UI对象中去。在同事的设计中,没有了EventLinkManager和LinkNode,取而代之的是ValueChangeMessageManager和MessageNode,ValueChangeMessageManager是静态类。从名字就可以看出,和消息有些关系。
这个设计的大致的工作模式是这样的:调用ValueChangeMessageManager.LoadValueChangeLink()方法载入数据传递关系,存入到LinkPathPairs集合中去,其中key为sourcepath,value则是targetpath;在ValueObejct类的Value属性Set方法中,每当Value值变化时,均调用ValueChangeMessageManager的QueueValueChangeMessage静态方法,传入自身路径及变化的值,QueueValueChangeMessage方法内,根据路径和变化值构造一个新的MessageNode对象,入队(MessageQueue);线程TakeValueChangeMessageThread则在不停的监视MessageQueue,当发现有新的MessageNode被入队后,弹出MessageNode对象,根据path检索LinkPathPairs获取targetpath,在根据targetpath去UiManager中搜索TargetObject,并调用相应的Value的Set方法,进而完成值的传递。这个传递过程其实是一个很基础的消息过程。只不过消息的管理者自身也完成了消息的消费。
当然,这仍然是一个简化设计,同样要考虑包括线程安全等一系列问题,甚至是否存在可复用的消息框架(PS:应该有很多)。
谁赢了呢?各设计都有什么优缺点呢?谁的设计更合理呢?
——好吧,这确实是个问题……