设计模式之 责任链设计模式 上 概念

责任链设计模式就是将原本复杂的混合在一起的处理逻辑进行拆分,按照业务、相关性等因素拆分到多个处理器中,每个处理器只负责一部分逻辑处理;在执行的时候,一个处理器接一个处理器的从前到后的执行,在结构上看就像一个链条,这也是责任链名字的由来。

责任链设计模式能够让代码结构更清晰,更易于应对日后的功能扩展。

场景举例

比如一张优惠券,在使用的时候,后台代码要根据下单信息来判断这张优惠券是否可用,涉及判断的条件非常多,判断因素假设包含:

1、坎级,比如这张优惠券需要满100减10,满200减20,那么当前订单金额是否满足100元或200元;

2、品牌或品类,比如这张优惠券只能用在购买康师傅品牌的商品;

3、支付类型,只能线上支付时使用这张优惠券;

4、可用对象,只有购买平台自售商品才能使用这张优惠券,购买三方店铺商品则不能使用这张优惠券(类似京东某些券只能购买平台自营商品)。

实际上的业务可能包含更多条件和因素,实际的判断逻辑也会更复杂。

如果我们将这些平铺直叙的堆砌到代码里,实际可能一个类中按照不同因素,添加多个方法,最终有一个入口方法组织这些方法来判断。

代码类似于:

//判断坎级方法
public boolean 坎级(Coupon c) {
    ...
}

//判断品牌或品类方法
public boolean 品牌或品类(Coupon c) {
    ...
}

//判断支付类型方法
public boolean 支付类型(Coupon c) {
    ...
}

//判断可用对象方法
public boolean 可用对象(Coupon c) {
    ...
}

//判断优惠券是否可用入口方法
public boolean 入口(Coupon c) {
    坎级(Coupon c)
    品牌或品类(Coupon c)
    支付类型(Coupon c)
    可用对象(Coupon c)
    return 结果
}

上面这种写法相对还能够接受,但是如果有的开发者直接一个大方法包含了所有逻辑(搞一个5000行代码的方法),这对以后业务变更后的升级改造挖下了一个大大的坑。

那么我们用责任链如何改造呢?

1、首先定义接口,接口中定义handle方法

public interface IHandler {

    boolean handle();
}

2、按照业务需要实现4个处理器,都实现了IHandler 接口,并实现了handle方法

import java.util.Random;

/**
 * 坎级
 */
public class HandlerA implements IHandler {
    @Override
    public boolean handle() {
        Random r = new Random();
        //生成随机整数,能被2整除表示业务逻辑为true,否则为false
        boolean b = r.nextInt(10)%2 == 0;
        System.out.println("exec 坎级:" + b);
        return b;
    }
}
import java.util.Random;

/**
 * 品牌或品类
 */
public class HandlerB implements IHandler {
    @Override
    public boolean handle() {
        Random r = new Random();
        boolean b = r.nextInt(10)%2 == 0;
        System.out.println("exec 品牌或品类:" + b);
        return b;
    }
}
import java.util.Random;

/**
 * 支付类型
 */
public class HandlerC implements IHandler {
    @Override
    public boolean handle() {
        Random r = new Random();
        boolean b = r.nextInt(10)%2 == 0;
        System.out.println("exec 支付类型:" + b);
        return b;
    }
}
import java.util.Random;

/**
 * 可用对象
 */
public class HandlerD implements IHandler {
    @Override
    public boolean handle() {
        Random r = new Random();
        boolean b = r.nextInt(10)%2 == 0;
        System.out.println("exec 可用对象:" + b);
        return b;
    }
}

3、责任链执行

import java.util.ArrayList;
import java.util.List;

public class Client {

    void handle(List<IHandler> hl) {
        System.out.println("---全部执行---");
        for(IHandler h:hl) {
            //不管每个处理器的验证结果是否为true,都会把处理器执行一遍
            h.handle();
        }
    }

    void handle2(List<IHandler> hl) {
        System.out.println("---某个执行器验证不通过则退出执行---");
        for(IHandler h:hl) {
            //如果验证不通过直接退出执行
            if(!h.handle()) {
                break;
            }
        }
    }

    public static void main(String[] args) {
        List<IHandler> hl = new ArrayList<>();
        IHandler ha = new HandlerA();
        IHandler hb = new HandlerB();
        IHandler hc = new HandlerC();
        IHandler hd = new HandlerD();
        hl.add(ha);
        hl.add(hb);
        hl.add(hc);
        hl.add(hd);
        Client c = new Client();
        c.handle(hl);
        c.handle2(hl);
    }
}

我们的责任链的每个处理器用的list来保存,就是main函数的这段代码:

List<IHandler> hl = new ArrayList<>();
        IHandler ha = new HandlerA();
        IHandler hb = new HandlerB();
        IHandler hc = new HandlerC();
        IHandler hd = new HandlerD();
        hl.add(ha);
        hl.add(hb);
        hl.add(hc);
        hl.add(hd);

然后在handle方法中使用循环依次执行,最终形成了一个链条执行的效果。

这里的demo实现了两个handle方法,handle方法是不管每个处理器的验证结果是否为true,都会把处理器执行一遍,handle2方法是某个执行器验证不通过则退出执行,这个可以按照实际的业务场景需要来定。

其实责任链还有一种模式,就是每个handler类都持有下一个handle,也就是在上面demo的HandlerA 、HandlerB、HandlerC、HandlerD中定义一个IHandler接口类型的元素,这样每个处理器就可以保存这个处理器之后的处理器,这样再当前hander类执行完handle方法后,可以直接调用下一个handler的handle方法,这种更像是一种责任链。代码如下:

  IHandler ha = new HandlerA();
        IHandler hb = new HandlerB();
        IHandler hc = new HandlerC();
        IHandler hd = new HandlerD();
        ha.setHandle(hb);
        hb.setHandle(hc);
        hc.setHandle(hd);       

这样不使用list,也可以是多个处理器形成一个链条。

总结:

责任链就是将复杂的处理逻辑进行拆分,拆分成多个的处理器来逐个处理,各个处理器形成一个链条,每个处理器处理完后再传递给后续处理器继续处理。

责任链设计模式适用于复杂的逻辑判断处理的场景。