大家好,今天和大家来聊一个新的设计模式——订阅者模式。

这个模式在我们的生活当中非常常见,可以说是几乎所有的媒体平台都用或多或少地用到了这个模式。比如公众号,我们来仔细梳理一下公众号这个平台当中的整个逻辑,会发现其实这里面一共有三方存在,这三方呈一个三角关系。

三方订阅关系

画出来的话大概是这个样子:


这张图大家应该很好理解,TechFlow每天把新的文章发布到公众号平台上,平台会把内容推送给那些关注了TechFlow的用户,大家正是因为关注了TechFlow才读到了这篇文章。

所以在订阅制的内容平台当中,其实是一个三方关系,而不是读者和作者两方关系,平台在当中起到了媒介的作用。只是很多时候作为读者,我们可能会忽略平台的存在。

既然存在三方关系,我们在实现相关逻辑的时候就需要把这三方剥离出来,单独实现各自的逻辑,这样代码的耦合性才最低,可以更加方便以后的拓展。

代码实现

订阅者模式其实没有太多内容需要讲,我们只需要记住一点,就是尽量让属于不同实体的代码逻辑分开,而不是耦合在一起就可以了,没有太多其他的门道。

我们先来看这个模式当中最简单的部分,也就是Publisher(作者)这个部分。对于作者而言,它是最简单的,因为它能做的事情非常少,就只有发布内容而已。当然一般现在也会有一些作者保护机制,比如说可以拉黑一些不喜欢的用户什么的,但这里我们不需要考虑那么多,只需要考虑基本功能就行了。对于作者而言,最基本的功能就是发布内容。

代码非常简单,就只有几行。

class Publisher:    def __init__(self, msg_center):        self.provider = msg_center    def publish(self, msg):        self.provider.notify(msg)

因为作者自身是没办法发布内容的,作者是把要发布的内容上传到平台,平台代替作者去发布的。体现在这个类当中就是我们调用了provider也就是平台去执行通知(notify)的操作,把新发布的内容推送到读者端。

读者端稍微复杂一点,因为读者不仅可以订阅,还可以取关,并且收到了消息之后还可以打开以及一些互动。这里我们把功能简化,就留下了三个最基本的功能,分别是关注、取关以及操作。

class Subscriber:    def __init__(self, name, msg_center):        self.name = name        self.provider = msg_center    def subscribe(self, msg):        self.provider.subscribe(msg, self)    def unsubscribe(self, msg):        self.provider.unsubscribe(msg, self)    def run(self, msg):        print('{} got {}'.format(self.name, msg))

从代码当中我们可以看到,读者端的操作其实也是和平台交互。平台是读者和作者之间的媒介,读者和作者之间不直接发生关联。这其实是非常不错的设计,如果关联和依赖很多,就会出现要开发新功能的时候畏手畏脚,会影响其他模块的情况发生。

最后,我们来看平台的部分,平台的部分其实也不复杂,只是用一个dict存储了读者和作者之间的订阅关系而已。其实这里没必要使用setdefault,使用defaultdict会更好。

class Provider:    def __init__(self):        self.msg_queue = []        self.subscribers = {}    def notify(self, msg):        self.msg_queue.append(msg)    def subscribe(self, msg, subscriber):        self.subscribers.setdefault(msg, []).append(subscriber)    def unsubscribe(self, msg, subscriber):        self.subscribers[msg].remove(subscriber)    def update(self):        # 遍历所有的作者        for msg in self.msg_queue:            # 遍历所有订阅了msg的读者进行推送            for sub in self.subscribers.get(msg, []):                sub.run(msg)        self.msg_queue = []

这里我把执行的测试代码也放上来,大家感兴趣可以自己试验一下。

if __name__ == '__main__':    message_center = Provider()    fftv = Publisher(message_center)    jim = Subscriber('jim', message_center)    jim.subscribe('cartoon')    jack = Subscriber('jack', message_center)    jack.subscribe('music')    gee = Subscriber('gee', message_center)    gee.subscribe('movie')    vani = Subscriber('vani', message_center)    vani.subscribe('movie')    fftv.publish('cartoon')    fftv.publish('music')    fftv.publish('ads')    fftv.publish('cartoon')    fftv.publish('cartoon')    fftv.publish('movie')    fftv.publish('blank')    message_center.update()

从代码层面来说,这个设计模式没有太多的难度,主要是一种解耦的思想。这一个思想很重要,在实际开发当中,我们决不能仅仅满足于实现产品经理的功能,因为产品经理往往是不懂这些系统之间架构和软件工程的。我们之所以需要设计模式只有30%的原因是为了更好的效率以及更简洁的代码,剩下70%的原因其实都是为了抵御日后功能需求的变化。

废话不多说了,今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、在看、转发)

©著作权归作者所有:来自51CTO博客作者wx6087db7ed1cb2的原创作品,如需转载,请注明出处,否则将追究法律责任

你的鼓励让我更有动力

赞赏

0人进行了赞赏支持

更多相关文章

  1. 大型三甲医院基础集成信息平台架构设计案例
  2. 合约跟单系统开发方案【现成源码】
  3. 智慧公安情报研判系统开发,重点人员可视化分析平台搭建
  4. 阿里Goldeneye业务监控平台之架构演进,如何实时处理100T+/天的日
  5. 代码管理平台GITLAB
  6. 代码管理平台GIT
  7. 代码管理平台SVN
  8. 自动化运维管理平台OpsManage部署
  9. 金融企业容器云平台架构设计需要清楚的8个问题

随机推荐

  1. 浅谈XML文档的阅读与编辑
  2. XML中的代码注释书写方法的详解
  3. XML中的模式Schema代码详细介绍(图)
  4. 深入理解XML中的字符实体与字符数据
  5. 详解SQL对Xml字段的操作示例代码(图)
  6. XML对代码中的空白处理详细介绍
  7. 详解Android实现XML解析技术(图)
  8. XML中处理指令的代码详解
  9. 详细介绍XML Web Service图文代码实例
  10. 详细介绍XML代码编写的编码与验证问题