职责链模式
职责链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。由于英文翻译的不同,职责链模式又称为责任链模式,它是一种对象行为型模式。
使用频率:中低
职责链模式
典型的抽象处理者代码:
public abstract class Handler
{
protected Handler successor;
public void setSuccessor(Handler successor)
{
this.successor=successor;
}
public abstract void handleRequest(String request);
}
典型的具体处理者代码:
public class ConcreteHandler extends Handler
{
public void handleRequest(String request)
{
if(请求request满足条件)
{
...... //处理请求;
}
else
{
this.successor.handleRequest(request); //转发请求
}
}
}
假设我们负责一个售卖手机的电商网站,经过分别交纳 500元定金和 200元定金的两轮预定
后(订单已在此时生成),现在已经到了正式购买的阶段。
公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过 500元定金的用
户会收到 100元的商城优惠券,200元定金的用户可以收到 50元的优惠券,而之前没有支付定金
的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。
我们的订单页面是 PHP吐出的模板,在页面加载之初,PHP会传递给页面几个字段。
var order = function (orderType, pay, stock) {
if (orderType === 1) { // 500 元定金购买模式
if (pay === true) { // 已支付定金
console.log('500 元定金预购, 得到 100 优惠券');
} else { // 未支付定金,降级到普通购买模式
if (stock > 0) { // 用于普通购买的手机还有库存
console.log('普通购买, 无优惠券');
} else {
console.log('手机库存不足');
}
}
} else if (orderType === 2) { // 200 元定金购买模式
if (pay === true) {
console.log('200 元定金预购, 得到 50 优惠券');
} else {
if (stock > 0) {
console.log('普通购买, 无优惠券');
} else {
console.log('手机库存不足');
}
}
} else if (orderType === 3) {
if (stock > 0) {
console.log('普通购买, 无优惠券');
} else {
console.log('手机库存不足');
}
}
};
order(1, true, 500); // 输出: 500 元定金预购, 得到 100 优惠券
虽然我们得到了意料中的运行结果,但这远远算不上一段值得夸奖的代码。 order 函数不仅
巨大到难以阅读,而且需要经常进行修改。虽然目前项目能正常运行,但接下来的维护工作无疑
是个梦魇。恐怕只有最“新手”的程序员才会写出这样的代码。
现在我们采用职责链模式重构这段代码,先把 500 元订单、200 元订单以及普通购买分成 3
个函数。
接下来把 orderType 、 pay 、 stock 这 3个字段当作参数传递给 500元订单函数,如果该函数不
符合处理条件,则把这个请求传递给后面的 200元订单函数,如果 200元订单函数依然不能处理
该请求,则继续传递请求给普通购买函数,代码如下:
// 500 元订单
var order500 = function (orderType, pay, stock) {
if (orderType === 1 && pay === true) {
console.log('500 元定金预购, 得到 100 优惠券');
} else {
order200(orderType, pay, stock); // 将请求传递给 200 元订单
}
};
// 200 元订单
var order200 = function (orderType, pay, stock) {
if (orderType === 2 && pay === true) {
console.log('200 元定金预购, 得到 50 优惠券');
} else {
orderNormal(orderType, pay, stock); // 将请求传递给普通订单
}
};
// 普通购买订单
var orderNormal = function (orderType, pay, stock) {
if (stock > 0) {
console.log('普通购买, 无优惠券');
} else {
console.log('手机库存不足');
}
};
// 测试结果:
order500(1, true, 500); // 输出:500 元定金预购, 得到 100 优惠券
order500(1, false, 500); // 输出:普通购买, 无优惠券
order500(2, true, 500); // 输出:200 元定金预购, 得到 500 优惠券
order500(3, false, 500); // 输出:普通购买, 无优惠券
order500(3, false, 0); // 输出:手机库存不足
可以看到,执行结果和前面那个巨大的 order 函数完全一样,但是代码的结构已经清晰了很
多,我们把一个大函数拆分了 3个小函数,去掉了许多嵌套的条件分支语句。