行为型模式——责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern)

责任链模式也叫职责链模式(Chain of Responsibility Pattern)属于行为型模式

什么是责任链模式?

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止

UML

责任链模式

角色
  • **抽象处理者(Handler)**角色:定义一个抽象的请求处理接口,其中包含下一个处理接口。
  • **具体处理者(Concrete Handler)**角色:实现抽象处理者的处理方法,先判断能否处理本次请求,再根据实际情况进行处理或者传递到下一个具体处理者处理。
  • **客户类(Client)**角色:创建处理链并向链头的具体处理者对象提交请求。
应用
使用模板
public class ChainOfResponsibilityPattern {
    public static void main(String[] args) {
        //创建并设置责任链
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();
        handlerA.setNext(handlerB);
        handlerB.setNext(handlerC);
        //责任链处理请求
        handlerA.handleRequest("A");
        handlerA.handleRequest("C");
        handlerA.handleRequest("D");
    }
}
//抽象处理者
abstract class Handler {
    //存储后续处理者
    private Handler next;
    //设置后续处理者
    protected void setNext(Handler next) { this.next = next; }
    //获取后续处理者
    public Handler getNext() { return next; }
    //处理请求
    public abstract void handleRequest(String request);
    //未被处理的通用方法,该处抽象到父类只是为了代码的简洁
    protected void finished(String request){
        if (getNext() != null) {
            getNext().handleRequest(request);
        } else { System.out.println("职责链执行结束,请求未被处理!"); }
    }
}
//具体处理者角色A
class ConcreteHandlerA extends Handler {
    //重写处理请求的方法
    @Override
    public void handleRequest(String request) {
        //判断是否需要该处理者处理
        if (request.equals("A")) {
            System.out.println("该请求已被处理——具体处理者A");
        } else { finished(request); }
    }
}
//同上
class ConcreteHandlerB extends Handler {
    public void handleRequest(String request) {
        if (request.equals("B")) {
            System.out.println("该请求已被处理——具体处理者B");
        } else { finished(request); }
    }
}
//同上
class ConcreteHandlerC extends Handler {
    public void handleRequest(String request) {
        if (request.equals("C")) {
            System.out.println("该请求已被处理——具体处理者C");
        } else { finished(request); }
    }
}

为什么要使用责任链模式?

优点
  1. 解耦。它将请求的发送者和接收者解耦,请求发出者不需要知道链的结构,弱化了请求发出者和请求处理者之间的关系。
  2. 灵活。客户端可以动态的组合责任链,通过增减链内的成员或者调动它们的次序。
  3. 专职。让各个处理者专注于实现自己的职责,无需过多的关注其他问题。
缺点
  1. 漏处理请求。不能保证请求一定被接收。
  2. 影响性能。如果责任链太长 , 或责任链中请求的处理时间过长 , 可能会影响性能 。
  3. 复杂。责任链可能过多 ,而且引用不当会死循环。

怎样使用责任链模式?

职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

适用场景:
  • 多个对象可以处理同一请求,但不确定具体由哪个对象处理,在运行时需要动态决定。
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
使用举例:
  • 系统的登录流程,验证码、账号、密码等,作为一个责任链每个处理者负责各自的部分。
  • javax.servlet.Filter#doFilter()
  • java.util.logging.Logger#log(LogRecord record)
举例分析

java.util.logging.Logger#log(LogRecord record)

角色对应关系

该类对应了抽象与具体处理者。

  • 其中Logger parent存储的后续处理者
  • void log(LogRecord record)处理请求。
package java.util.logging;
...
public class Logger {
...
//该类的上一级日志对象
private volatile Logger parent;    // our nearest parent.
...
public void log(LogRecord record) {
        ...
        //当前的日志(不确定上一级日志对象)是否存在,并且进入循环。
        Logger logger = this;
        while (logger != null) {
            //细节处理
            ...
            //此处判断是否需要使用其上级日志处理
            final boolean useParentHdls = isSystemLogger
                ? logger.useParentHandlers
                : logger.getUseParentHandlers();
			//如果无需使用上级处理则跳出循环
            if (!useParentHdls) {
                break;
            }
			//该处为切换到上级处理对象继续进行执行循环体,直到需要的顶级日志处理,通过上一步结束该循环体。
            logger = isSystemLogger ? logger.parent : logger.getParent();
        }
    }
...
}

在上述代码中,合并了抽象处理者具体处理者,但是依旧使用的责任链的逻辑。后续的使用仅仅需要创建不同级别的日志对象,再将不同的按照顺序放入下一个级别的属性parent中。

拓展

职责链模式存在以下两种情况。

  1. 单纯职责链模式:一个请求一定会被某个处理者处理,而且是单独处理。
  2. 复杂的职责链模式:一个请求不一定会被处理,可能会被多个处理者同时处理。
    的逻辑。后续的使用仅仅需要创建不同级别的日志对象,再将不同的按照顺序放入下一个级别的属性parent中。

拓展

职责链模式存在以下两种情况。

  1. 单纯职责链模式:一个请求一定会被某个处理者处理,而且是单独处理。
  2. 复杂的职责链模式:一个请求不一定会被处理,可能会被多个处理者同时处理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值