设计模式-builder模式(以微信消息的路由处理为例)

今天要讲一个简单的模式–builder模式。
你可能会觉得,builder模式有什么好讲的?本来我也这样觉得,但当我有幸拜读某位大神通过builder模式写了一个开发工具包的初始化操作,嗯代码的样子很叼
这位大神是谁呢?
在这里插入图片描述
就是这位仁兄啦,是码云上一个很火的微信开发工具包的贡献者之一。

在这里插入图片描述
一、言归正传,让我们来先看下业务:
(1)目标:
对微信端传来的用户消息进行处理。
(2)需要解决的问题:
消息类型多:微信推送给公众号(即绑定的应用服务器)的消息类型很多,我们需要针对用户不同的输入做出不同的反应。
(3)一般的解决方式:
if(msgType.equals(“text”)){
doSomething();
} else if(msgType.equals(“image”)){
doSomething()
} else if(msgType.equals(“event”)){
if(event.equals(“subscribe”)){
doSomething();
}else if(event.equals(“click”)){
doSomething();
}

}

嗯,很low的写法~

二、知道了业务和一般的实现方式后,我想你对需要做的事有了一定的了解,现在来看看大神是怎么实现多种类型的消息的处理的。

1.先定义一个消息路由器(简称Router),他是“消息处理器”的抽象。
2.为了实现“开闭原则”和“单一职责”的设计原则,“处理消息”这个功能肯定要单独拿出来,将之定义为MessageHandler
3.然后我们也不能对所有的消息都做处理,所以肯定需要过滤器,在这里我们将过滤器称之为规则(Rule),即符合规则的就进行处理。

所以,从逻辑上来看,大体就是“消息处理器”(Router)包含MessageHandler和Rule。在最外层,我们使用Router进行消息处理。

不过,这么理解其实是有错误的,哈哈~~
再仔细思考下流程,我们应该是先对消息进行规则的匹配,匹配通过了,才对消息进行处理。所以应该是Rule包含MessageHandler。

那么整体的结构就是:Router包含Rule,而Rule又包含MessageHandler。

三、接下来就是代码构建环节,先看看到底是怎么使用的吧。
在这里插入图片描述

可以看到我们在微信的配置类里创建了一个Router对象,进行统一的消息路由处理。
然后Router对象是怎么创建的呢?
可以看到,我框出来的2个核心方法rule()和handler()。rule()就是创建匹配规则,对消息进行过滤(之后的msgType()、event()就是表明对哪个特定类型的微信事件进行规则的匹配);而handler()就是将某个特定的处理器赋予规则,让规则匹配的时候可以对消息进行相应的处理。

看到这你可能会问,rule和handler是有了,那它们是怎么赋值给Router对象的呢?

答案就是链式调用最后的next()或end()方法。

先来看看rule()方法到底干了什么吧~
Router.rule()方法如下:
在这里插入图片描述
可以看到,router再创建rule对象的时候,把router自己给传了进去。

再来看rule对象的next()或end()方法:

在这里插入图片描述
在这里插入图片描述
可以看到next()就是调用了end()方法,只是把reEnter属性设置为true(reEnter默认为false),表示可以继续处理下面的规则,即对消息进行多重处理(如日志规则处理完后再做其他业务规则的匹配)
当然啦,最核心的就是调用了Router对象getRules()方法,将自己(rule对象)传递给Router对象。
在这里插入图片描述
可以看到,Router对象里维护了一个Rule数组。

这样,Router对象就“不知不觉”间有了很多的rule对象,而各个rule对象设置了不同的规则属性和handler对象,整个Router就丰满了起来~

到这里,微信消息路由的设计已经讲的差不多了,再补充几个小的知识点:
1.builder模式的一个特征就是使用链式调用,即设置属性的方法的返回值是对象本身,而不是void,举个例子:

在这里插入图片描述
这里Rule对象的msgType()和event()方法就是设置属性的方法,而返回的Rule对象本身,这样就可以达到链式调用。

2.可以看到,Rule对象最后的end()或next()方法返回的是Router对象,所以还可以这样链式调用:
在这里插入图片描述
就是这样一直“点”下去,哈哈。当然了,这样的调用没有之前那么清晰,就不用刻意地链式调用下去了,这里只是为了演示链式调用的做法。

3.你可能还会好奇规则(rule)到底是怎么匹配微信传来的消息的,其实也很简单:
在这里插入图片描述
在这里你可以看到匹配规则的收集和规则的重入(之前说的reEnter属性),reEnter为false的时候只会收集自己这一条规则。(所以rule在list中的顺序也有讲究哦:配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理)
言归正传,Router对象要使用哪条规则其实是看Rule对象的test()方法。再来一起看看它:
在这里插入图片描述
可以看到,就是先看Rule对象自己有没有这些属性。若有其中某些属性,如:fromUser、msgType等,说明这些属性就是要关注的匹配项,如果后面的this.fromUser.equals(wxMessage.getFromUser())或this.msgType.equalsIgnoreCase(wxMessage.getMsgType())为false,说明匹配不通过,这条微信消息不适用这条Rule来处理。
如果Rule对象一条属性都没有,那么这个test是匹配通过的!(通过代码可以容易看出,所有”&&”关联的都为true)

总结下来,你为Rule对象设置的属性越多,那这就是一个越细分场景的处理规则;相反,若你一个属性都不设置,那这就是一个通用的规则。(如:日志规则,只设置了个hander)
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值