设计模式学习(10)——行为型模式之“责任链设计模式“

一、介绍

责任链模式是把多个对象串联起来形成一个链状结构,让每个对象都有机会对事件发送者的请求进行处理。设计意图是为了使事件发送者和事件接受者之间解耦。责任链模式包含一份请求对象和一系列执行对象,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

是一种处理请求的模式,请求在链上传递。

责任链模式解决的问题:

(1)请求者和接受者松散耦合

在责任链模式中,请求者并不知道接受者是谁,也不知道具体如何处理。请求者只负责向责任链发出请求就可以了,该模式下可以有多个接受者处理对象,每个接受者只负责处理自己的部分,其他的就交给其他的接受者去处理。请求在链中传递,接受者处理该请求,或者传递给链中下一个接受者。请求者不再和特定接受者紧密耦合。

(2)通过改变链内成员的或者调整它们的次序,允许你动态地新增或删除责任。

 使用场景:

(1)当一个请求需要根据请求参数的不同由不同对象来处理时候。

(2)当一个请求需要固定对象顺序处理,并且可扩展性的在固定顺序里面插入新的对象进行处理时候。

二、责任链模式示例

2.1、案例1:财务审批

假设某个员工需要报销一笔费用,审核者可以分为:

  • Manager:只能审核1000元以下的报销;
  • Director:只能审核10000元以下的报销;
  • CEO:可以审核任意额度。

用责任链模式设计此报销流程时,每个审核者只关心自己责任范围内的请求,并且处理它。对于超出自己责任范围的,扔给下一个审核者处理,这样,将来继续添加审核者的时候,不用改动现有逻辑。

实现步骤:

(1)抽象出请求对象,它将在责任链上传递

@Data
public class Request {
    private String name;
    private BigDecimal amount;
}

(2)抽象出处理器

并且做好约定:如果返回Boolean.TRUE,表示处理成功,如果返回Boolean.FALSE,表示处理失败(请求被拒绝),如果返回null,则交由下一个Handler处理。

public interface Handler {
    // 返回Boolean.TRUE = 成功
    // 返回Boolean.FALSE = 拒绝
    // 返回null = 交下一个处理
	Boolean process(Request request);
}

(3)编写具体处理者

依次编写ManagerHandler、DirectorHandler和CEOHandler。以ManagerHandler为例:

public class ManagerHandler implements Handler {
    public Boolean process(Request request) {
        // 如果超过1000元,处理不了,交下一个处理:
        if (request.getAmount().compareTo(BigDecimal.valueOf(1000)) > 0) {
            return null;
        }
        // 对Bob有偏见:
        return !request.getName().equalsIgnoreCase("bob");
    }
}

(4)有了不同处理者(Handler)后,还要把这些Handler组合起来,变成一个链,并通过一个统一入口处理:

public class HandlerChain {
    // 持有所有Handler:
    private List<Handler> handlers = new ArrayList<>();

    public void addHandler(Handler handler) {
        this.handlers.add(handler);
    }

    public boolean process(Request request) {
        // 依次调用每个Handler:
        for (Handler handler : handlers) {
            Boolean r = handler.process(request);
            if (r != null) {
                // 如果返回TRUE或FALSE,处理结束:
                System.out.println(request + " " + (r ? "Approved by " : "Denied by ") + handler.getClass().getSimpleName());
                return r;
            }
        }
        throw new RuntimeException("Could not handle request: " + request);
    }
}

(5)最后在客户端构造出责任链,然后用责任链来处理请求

// 构造责任链:
HandlerChain chain = new HandlerChain();
chain.addHandler(new ManagerHandler());
chain.addHandler(new DirectorHandler());
chain.addHandler(new CEOHandler());
// 处理请求:
chain.process(new Request("Bob", new BigDecimal("123.45")));
chain.process(new Request("Alice", new BigDecimal("1234.56")));
chain.process(new Request("Bill", new BigDecimal("12345.67")));
chain.process(new Request("John", new BigDecimal("123456.78")));

注意Handler添加的顺序很重要,如果顺序不对,处理的结果可能就不是符合要求的。

 

责任链模式的其余多种场景:

场景1:有些责任链的实现方式是通过某个Handler手动调用下一个Handler来传递Request

例如:

public class AHandler implements Handler {
    private Handler next;
    public void process(Request request) {
        if (!canProcess(request)) {
            // 手动交给下一个Handler处理:
            next.process(request);
        } else {
            ...
        }
    }
}

场景2:有一些责任链模式,每个Handler都有机会处理Request,通常这种责任链被称为拦截器(Interceptor)或者过滤器(Filter),它的目的不是找到某个Handler处理掉Request,而是每个Handler都做一些工作 

例如:

  • 记录日志;
  • 检查权限;
  • 准备相关资源;

例如,JavaEE的Servlet规范定义的Filter就是一种责任链模式,它不但允许每个Filter都有机会处理请求,还允许每个Filter决定是否将请求“放行”给下一个Filter

public class AuditFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        log(req);
        if (check(req)) {
            // 放行:
            chain.doFilter(req, resp);
        } else {
            // 拒绝:
            sendError(resp);
        }
    }
}

 

 

 

参考:https://www.liaoxuefeng.com/wiki/1252599548343744/1281319474561057

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值