使用 职责链模式 来优化代码吧
今天的这篇文章主要是讲 代码优化 层面,我个人认为,代码的质量体现了一个人的编码能力,也是一个项目是否能够快速迭代的关键因素之一。代码写得好,下班回家早
今天我们使用 职责链
模式来优化我们的代码
职责链模式
职责链模式:使多个对象都有机会处理请求,从而避免请求的
发送者
和接收者
之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
职责链模式的名字非常形象,一系列可能会处理请求的对象被连接成一条链,请求在这些对象之间依次传递,直到遇到一个可以处理它的对象, 我们把这些对象称为节点
, 如下图所示:
现实中的职责链模式
在以前坐公交车需要售票员的时候,如果在早高峰的时候,你上车的时候,需要找到售票员,因为人太多,不太好找,所以你拿着硬币去递给你的下一个人,如果他遇到了售票员,结束传递,如果不是,则继续往下传递,直到遇见售票员
可以很容易的发现,职责链模式的最大优点:请求发送者只需要知道链中的第 一个节点,从而弱化了发送者和一组接收者之间的强联系
。 如果不使用职责链模式,那么在公交车上,我就得先搞清楚谁是售票员,才能把硬币递给他
实际开发中的职责链模式
1. 售卖手机的电商网站
假设我们负责一个售卖手机的电商网站,经过分别交纳 500 元定金和 200 元定金的两轮预定后(订单已在此时生成),现在已经到了正式购买的阶段
公司针对支付过定金的用户有一定的优惠政策。 在正式购买后,已经支付过 500 元定金的用户会收到 100 元的商城优惠券,200 元定金的用户可以收到 50 元的优惠券,而之前没有支付定金 的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到
如果在开发过程中,我们一般都会这样定义字段
- orderType:表示订单类型(定金用户或者普通购买用户),code 的值为 1 的时候是 500 元定金用户,为 2 的时候是 200 元定金用户,为 3 的时候是普通购买用户。
- pay:表示用户是否已经支付定金,值为 true 或者 false, 虽然用户已经下过 500 元定金的订单,但如果他一直没有支付定金,现在只能降级进入普通购买模式。
- stock:表示当前用于普通购买的手机库存数量,已经支付过 500 元或者 200 元定金的用户不受此限制。
下面我们把这个流程写成代码:
普通写法
虽然这个代码运行良好,但是这个已经 order
方法已经非常巨大了,且难以理解,维护起来有一定的难度,如果再增加其他条件,代码理解会更加的困难
🚀 职责链模式优化
现在我们采用 职责链模式 重构这段代码,先把 500 元订单、200 元订单以及普通购买分成 3 个函数。
接下来把 orderType、pay、stock 这 3 个字段当作参数传递给 500 元订单函数,如果该函数不符合处理条件,则把这个请求传递给后面的 200 元订单函数,如果 200 元订单函数依然不能处理该请求,则继续传递请求给普通购买函数
代码如下:
是不是感觉逻辑变得更加的清晰了,就像一根链条依次执行,直到可以结束为止,即遇到终结条件为止;这种模式的好处是, 如果想要加一个 300 元的订单逻辑,可以很容易的加上一个 chainOrder300
,而不必修改其他代码,切合了开放封闭原则
用 AOP 实现职责链
在之前的职责链实现中,我们利用了一个 Chain 类
来把普通函数包装成职责链的节点。其实利用 JavaScript 的函数式特性,有一种更加方便的方法来创建职责链。代码如下
2. 验证密码格式 🐝
验证密码是很常见的需求,比如我们验证一个密码长度在 8, 16
位之间,类型是必须要有 大写英文
,小写英文
,数字
组成
你有可能写下如下代码
let regs = [/\w{6,9}/, /[a-zA-Z0-9]/];
let password1 = "123";
let password2 = "Abcdef123";
let r1 = regs.every((reg) => reg.test(password1)); // false
let r2 = regs.every((reg) => reg.test(password2)); // true
当然没有问题,但是如果验证密码需要多处用到,但是每次的要求都不一样,亦或者进行自定义的报错,这种简单写法的局限性就出来了,我们使用 职责链模式
进行扩展
我们定义一个 passwordChecker
类,其中的 rules
属性用来存放校验器,check
方法使用校验器校验密码
接下来我们定义校验器
1.长度校验器
- 类型校验器
校验结果
这样虽然说代码量增加了,但是可扩展性增强了,代码结构变的更加清晰,如果以后想要扩展,可以直接在校验类中添加方法
总结
代码优化就像是锦上添花,是在实现原有功能的基础上,进行的有目的优化,代码是给机器运行的,但更多的是给人看的,完成功能最基本的要求,在此基础上使用优化手段。
设计模式是先有的设计,是前辈们不断在实践中总结,最终形成的一种可复用模式,今天的职责链模式目的是代码更加强壮,可读性更强