给我一个婚介所,就能搞到一群姑娘! -- mediator(中介者)设计模式的精髓 .

来源:互联网 发布:linux ls显示文件名 编辑:程序博客网 时间:2024/04/27 13:26
 

引题

        今天看了非常给力的《艺龙旅行网架构案例分享 》http://www.infoq.com/cn/presentations/jzf-elong-architecture-case-study ,里面提到了mediator模式。 之前在学习设计模式的时候就注意到了这个模式,现在看了里面的几个应用非常受启发。

        mediator 解决的是多个对象之间关系复杂,连线太多的问题。它的目标就是要减少这些连线的数量,降低复杂度!像不像婚介所,本来我要维护一堆姑娘的联系方式,并还要自己一个个的找(她们也是如此维护和众男伴的关系),ok,现在包办给婚介所就好了。

    所以mediator模式的口号是:

  “给我一个婚介所,就能搞到一群姑娘!”

 

入题 

       在婚介所我们维护的是男女关系,那么在程序当中我们维护也是关系,画在纸上就是各种各样的“连线”,那么有哪几种连线呢?其实可以套用硬件总线的分类方法,当然首先你得连线的对象是谁,就像知道得找怎样的姑娘一样。

1) 数据: 要给什么?可以细为

               数据的格式,

               数据的内容

 

2) 控制: 怎么给?可以细为

               空间上怎么给 -- 调用关系依赖

               时间上怎么给 -- 同步的给,还是异步的等

 

3) 地址: 如何找到她?可以细分

               地址,她在哪?

               路由,如何找到她?

 

破题

视频当中使用了  i Spring IoC 

                              ii Canonical Data Format 、

                              iii SOA Enterprise Service BUS。按照上面的分类可以对号入座。


1) 数据

       最好理解的是数据,对应视频举例ii。

       几个对象之间传递数据,先转化成统一格式,每个对象接收后在转成自己的格式。

       而对于数据内容,这个类似于数据同步了,其实就是视频当中第一个配置文件分散、更改麻烦的问题。所以引入了一个中心节点,所有的配置文件都从这个节点上抓取。

       拿婚介所的例子来说,比如婚介所搞了一个网站,找姑娘?来,先注册,从我这里填写个表(统一的格式)。 想找什么样的姑娘,看我的公告牌,上面都是待嫁的好姑娘(统一的数据)。啊,阿猫阿狗已经牵手成功了,好好好,赶紧把他们从公告牌当中删除,我们也就看不到了,脑袋里面更不会有(数据的同步),简单不?

 

2) 控制

     控制的问题其实比较简单,mediator似乎是最想解决这个问题而诞生的。

对于空间上,比如函数func1(), func2(), func3()都分别放在x,y,z文件当中,模块A调用了func1() func2(), B调用了func2(), func3(),C调用了func3(),这里他们之间的调用连线是不是很多。 如果是把函数func1(), func2(), func3()都写在一个文件当中D, A,B,C只需要知道D, 或者说只需要调用D里面的函数就行了。

 

视频里面举那个流程改造的例子,我觉得非常的有启发性。里面的改造其实是从原始的状态机 分离成转发流程和处理流程 相互独立的过程。里面时间、空间的解耦都涉及了。 

    [1] 原始的状态机涉及到至少3个参数,

         A 事件 B当前状态 C下一个状态 = g ( A, B)

         g 在这里是一个单值函数,给出A,B就有唯一的C对应。一般是通过查一个二维表,

 

         但是大多情况下是5个参数

         A 事件 B当前状态 C 下一个状态

         D 对应的处理事件 D = f( A, B )

         E D的返回结果

    所以C呢,修正为C = g( A, B, E ), 或者是 g( A, B, f( A, B) ) ,  -- 其实还是g'(A,B) 嘛,但是从编程的角度我们不考虑这些简化。反过来,我们现在要做的是把f( A, B )从 g( A, B, f( A, B) ) 当中分离出去,C变成纯粹的C = g( A, B, E ) , 交给全局的状态转换引擎负责。1个

      D变成纯粹的D = f( A, B) , 交给当前状态节点的处理函数负责。还是多个

      OK,这样空间上解耦了吧。本质上就是把“当前该干什么”和“下一步是什么”给分离开来,呵呵。尽管对于人脑来说要走一步想三步,但是对电脑来说这样可不见得好。这样的好处是,对于流程节点来说,当业务发生变化的时候,比如上面视频提到的例子,对于VIP来说可以先买票 ==> 再出票 ==> 最后付钱,而一般会员和一次性顾客都得先付钱 ==> 再买票 ==> 最后出票, 

      只需要g( A, B, E ) 当中根据B, E 进行再细分,或者增加一个会员状态F,扩展成为 g( A, B, E, F ) 即可,你可能会说,此时无论如何都要修改g啊,是啊,可是这时候g已经从之前分散在各个节点当中的,被抽取出来放到那一个引擎当中去了,这时候只需要改一处即可!

    感受到mediator的威力了吧? 婚介所给力不,有木有? 

 

    [2] 时间上的分离,就更好理解了,即这个调用是异步的,还是同步的。如果是异步的,那么你调用了我,我什么是时候得到结果果再告诉你,你不必死等,是不是时间上分离了?

    这个过程发生在哪呢,发生在状态转换引擎得到E的时候,如果是引擎同步等待每个状态节点返回结果,那就没有时间上的分类了。但是视频里面使用了notify-dispatch的模式,就是引擎一个线程T1,维护一个消息队列Q。节点状态处理函数另一个线程T2。 T2就是把处理好的结果放入到Q当中,T1不停的轮询Q,有东西的时候算出来它的下一个状态是什么,然后就分发到下一个状态的节点。这时候因为异步的关系,T1得到E的时候已经丧失上下文了,所以T2最好是返回(A,B,E) 这样一个3元组P。然后T1根据P直接带入到g() 当中得到E。

     时间上的分离的好处我也就不必多说了。


        还是拿婚介所比喻, 

        空间上的分离:本来啊,你得漫无目的的在街上寻找姑娘,看到一个性感的背影,好了,空间上接近,迫不及待的想看她正面,然后心开始扑通扑通乱跳。有一句是什么来着,”望背影急刹千军万马“, 你那个兴奋啊,期待啊,可是。。。她一转身,”猛回头喝退各路诸侯“,原来是个如花啊!!!”我的妈呀“。  要是有婚介所就好了,这时候婚介所先帮你过滤了一批,你根本不需要接近这些姑娘鉴别美女。只需要看看婚介所给你的照片。。。(虽然国内PS流行)

        时间上的分离:你还不甘心,继续找啊找,好不容易发现了美女,总不能让她这样就走了把,于是你鼓起勇气,厚着脸皮, 要了她的联系方式,心中无比暗爽。  而婚介所事先就帮你要到了一堆美女的联系方式,你只要去找中介即可。这时候对你来说,"找"和"要联系方式" 不是同时进行的。

 

3)地址 

        视频的举例i 和iii 我认为都可归类到这里,为什么呢

        i举例是IoC, 解决对象依赖关系,这种依赖关系就是地址,

        如A要import com.b.c.d 下的东西,要知道这个com.b.c.d在哪,如何解析这个,是不是地址的问题?

        iii举例是SOA当中的Bus,解决对象之间通信的问题,既A要发给B,C,D这些对象,B要发给C, D, E, 但是呢,A, B又不想维护冗余的C,D的地址,这时候怎么办?是不是地址管理和路由的问题?其实学过网络,就知道路由器就是解耦这一过程而发明的。

        如果说两者一些区别在于后者还一个路由的问题,这个也好办,路由的过程,是不是路由器查找路由表然后把包按照某个地址发出去?好了,路由表也是一个数据型mediator(当然实际当中,每个路由器维护的路由表是不一样的,但是这里只考虑由一个路由器连接而组成的局域网),ok,现在这个路由表原来需要A,B,C,D 各种维护一份,现在好了,由这个数据由路由器来维护了一张公共的表,呵呵。

       相当于你去相亲,不需要事先知道每个姑娘住哪,她们也不需要知道你的,到了婚介所都会一一提供。

       连这个找路的路由算法都集中在路由器当中了,不需要每个节点都维护一份了。

       相当婚介所服务很到位,怎么去到姑娘家事先用google map 查了一份存好,你也不用自己在费脑筋、费时间去查了。每位姑娘来你家也是如此, 什么,来我家。。。。。

 

结题 

     所以一旦遇到”连线“数量增多的问题,使用mediator是一个好办法,

     如何分解这个问题,按照数据/控制/地址的方法分类,想想婚介所的例子,相信都能解决的。

     但是mediator也有个明显的缺陷,就是作为mediator的中心节点 单点失效的问题,这个就不在本篇讨论之列了

    一点愚见,敬请指教! 转载请注明作者和出处,谢谢!

原创粉丝点击