前端设计模式之职责链模式

模式动机

职责链模式

  • 职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。
  • 链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传递,由链上的处理者对请求进行相应的处理,客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,将请求的发送者和请求的处理者解耦。这就是职责链模式的模式动机。

模式定义

职责链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。由于英文翻译的不同,职责链模式又称为责任链模式,它是一种对象行为型模式
使用频率:中低
职责链模式

模式结构

前端设计模式之职责链模式_第1张图片
职责链模式包含如下角色:

  • Handler: 抽象处理者
  • ConcreteHandler: 具体处理者
  • Client: 客户类

模式分析

  • 在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链
  • 请求在这条链上传递,直到链上的某一个对象处理此请求为止。
  • 发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任

典型的抽象处理者代码:

 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会传递给页面几个字段。

  • orderType :表示订单类型(定金用户或者普通购买用户), code 的值为 1的时候是 500元 定金用户,为 2的时候是 200元定金用户,为 3的时候是普通购买用户。
  • pay :表示用户是否已经支付定金,值为 true 或者 false , 虽然用户已经下过 500元定金的 订单,但如果他一直没有支付定金,现在只能降级进入普通购买模式。
  • stock :表示当前用于普通购买的手机库存数量,已经支付过 500 元或者 200 元定金的用户不受此限制。
    下面我们把这个流程写成代码:
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个小函数,去掉了许多嵌套的条件分支语句。

模式优缺点

优点
  1. 降低耦合度
  2. 可简化对象的相互连接
  3. 增强给对象指派职责的灵活性
  4. 增加新的请求处理类很方便
缺点
  1. 不能保证请求一定被接收。
  2. 系统性能将受到一定影响,而且在进行代码调试时不太方便;可能会造成循环调用。

模式适用环境

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
  • 动态指定一组对象处理请求

模式应用

JavaScript事件浮升机制:
前端设计模式之职责链模式_第2张图片

你可能感兴趣的:(设计模式,设计模式)