设计模式在软件系统中的应用(一)之订阅模式

一直想把这么多年的设计经验归纳起来,但一直没有找到合适的切入点。软件设计的思想其实是比较凌乱的,有时候真的就是一种无法言传的经验之谈。比如你问一个很牛的架构师,什么是架构?答案各不相同。这就是软件设计,上到架构,下到编码,甚至测试设计,很多都是一些经验。

但是,我们很庆幸,老一辈的软件工程师也意识到了这个问题,他们将一些通用的设计思想和方法,用了一种通用的表达方式和定义,加以描述和总结,形成了所谓的“设计模式”,造福了后代无数的跟随者,你我就是其中的一个。

提到设计模式,都会想到四人帮(Gang of four)的经典之作《设计模式》Design pattern,这是一部神作,归纳出来的多种设计模式成了后人仿效和专研的对象,我拜读了多次,可惜始终没能读懂领会。

后来,在工作中接触到了一些模块设计、系统设计甚至架构方面的设计,慢慢领会到了一些所谓的“模式”。原来,他们离我们并不远,只是我们没有去发现。让我们用设计模式,串起我的一些设计经验,一起来发现模式之美。

PS:下面所有的例子都不假设编程语言,不讲具体的编程实现,只描述通用方法。

一、订阅

什么是订阅?你到邮局订阅报刊杂志,你用微博关注某人成为其粉丝,你用RSS订阅某网站的新闻......这些都是订阅。从数据流来分析订阅的本质,其实是一种数据生产者到数据消费者的点对多点的通信方式,有点绕,看下面图:



但是上图表示出来的概念并不是“订阅”,而是notify,他们的区别在哪里呢?没错,动作的主动方和被动方反的。如果生产者主动发送数据,我们叫做notify,也就是推送模式。而消费者申请数据,这种方式才叫做订阅。下图所示,我们认为是订阅方式:



好了,我们明确了订阅模式的概念,那么,为什么要使用订阅模式呢?从上面两个图来看,notify和订阅,两种方式的数据流是相同的,不同的是生产者是主动还是被动发送数据更新消息。这就是订阅模式的关键所在。

在许多场景中,生产者不应该感知消费者的差异。通俗一点,杂志社不应该感知读报纸的人的个体差异,是男的女的、老人小孩、还是胖子瘦子。对于杂志社来说,都是通过邮局来将最新的报纸发布给消费者。可以试想一下,如果杂志社的报纸配送方式,随着消费者的差异都做特殊处理的话,那会是一个灾难。

从软件模块的角度来说,也是类似的道理。我们来看看订阅模式的一个典型应用:

通过订阅解除模块的反向依赖



上面是一个系统的简单分层的一部分,应用层位于协议层上面,按照系统分层的原则,为了保持系统底层的稳定,我们规定上层可以访问下层,但是下层不能访问上层(后面会专门介绍系统分层模式)。但是,我们很多系统中,会从底层产生一些事件,并且需要通知到应用层。很简单的一个例子,比如底层的接口故障,需要通知到应用层,应用需要给用户报故障等。如果使用notify模式,那么模块2需要感知模块1的存在,很显然违背了系统分层原则,形成了反向依赖(反向依赖的危害后面专门讲)。

如何解决这个问题?没错,采用订阅方式。



模块1首先向模块2发送一个订阅请求,模块2存储一个订阅的映射关系,这个映射关系是通用的。模块2的数据变化后,从这个映射关系中找到数据的订阅者,分别向这些订阅者发送通知。这种方式和上面方式的区别在于,模块2不会为模块1做硬编码,这样避免了模块2对模块1的强依赖。这样,如果在应用层增加一个模块3同样需要感知这个数据时,模块2的代码不需要做任何改动。这样,就解除了反向依赖。


订阅是系统设计中非常常用的一种模式,在实现上可能稍显啰嗦(因为需要维护一个消费者的映射关系),没有notify那么来得直接。但是从模块的耦合、架构的可扩展性上来说,订阅是非常必要的一个手段,尤其对一些大规模的软件系统尤为关键。

本文描述中涉及到了很多东西,比如分层模式,数据流等等,后面会专门描述,敬请期待......

(如果你喜欢本文,请转载,但是一定要贴上我的博客地址哈,非凡技术博客http://blog.csdn.net/j00105840)


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值