设计模式(13)-责任链模式

简介

为什么要使用责任链模式

在软件系统中,有能力处理客户端请求的对象可能不止一个。客户端发送请求后,怎么安排对象处理请求是个问题。职责链模式可以将这些请求的处理者组织成一条链,请求沿着这条链传递,直到有对象可以处理它为止。客户端无需关系处理的细节以及请求的传递,只需要将请求发送到链上即可。

什么是责任链模式

职责链模式(Chain of Responsibility Pattern):使多个对象都有机会处理请求,从而避免请求发送者与接收者耦合在一起。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

类型

对象行为型模式

遵循的原则
迪米特法则、开闭原则

角色

角色

  • Handler:抽象处理者
    • 一般是抽象类。定义了处理请求的接口。
    • 定义了请求处理抽象方法handleRequest(),规范了子类处理请求的操作。
    • 为了将处理者组成一条链,抽象处理者需要返回一个本处理者的下个处理者的引用。由于处理者的下方还是处理者,因此在抽象处理者中定义了一个抽象处理者类型的对象(如结构图中的successor),作为下个处理者的引用(可选)。
  • ConcreteHandler:具体处理者
    • 继承Handler的具体处理者角色。
    • 实现了handleRequest()抽象方法来处理请求。
    • 具体处理者接到请求后,如果可以处理就将请求处理掉;否则通过对下个处理者的引用将请求转发给下个处理者。
  • Client
    • 客户。向链上提交清求。

UML类图

chainOfResponsibility.png

实现

  • 创建抽象处理者角色Handler.java
  • 创建具体处理者角色ConcreteHandler.java、ConcreteHandler2.java
  • 创建客户端Client.java

抽象处理者角色Handler.java

abstract class Handler {
    // 持有后继的责任对象
    protected Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public Handler getSuccessor() {
        return successor;
    }

    // 根据具体需要来选择是否传递参数
    public abstract void handleRequest(String judging);
}

具体处理者角色

ConcreteHandler.java

class ConcreteHandler extends Handler {
    /**
     * 请求处理方法,调用此方法处理请求
     */
    @Override
    public void handleRequest(String judging) {
        // 判断请求是否满足条件,这里随便设置个条件
        boolean isTrue = judging == null ? true : false;
        /*
         * 如果满足条件,则处理;如果没不满足,则转发请求请求
         */
        if (isTrue) {
            System.out.println(this.getClass().getSimpleName() + "处理请求");
        } else {
            System.out.println(this.getClass().getSimpleName() + "转发请求");
            this.successor.handleRequest(judging); // 转发请求
        }
    }
}

ConcreteHandler2.java

public class ConcreteHandler2 extends Handler {

    /**
     * 请求处理方法,调用此方法处理请求
     */
    @Override
    public void handleRequest(String judging) {
        // 判断请求是否满足条件,这里随便设置个条件
        boolean isTrue = judging == null ? false : true;
        /*
         * 如果满足条件,处理;如果不满足,则转发请求请求
         */
        if (isTrue) {
            System.out.println(this.getClass().getSimpleName() + "处理请求");
        } else {
            System.out.println(this.getClass().getSimpleName() + "转发请求");
            this.successor.handleRequest(judging); // 转发请求
        }
    }

}

客户端Client.java

public class Client {
    public static void main(String[] args) {
        // 组装责任链
        Handler handler1 = new ConcreteHandler();
        Handler handler2 = new ConcreteHandler2();
        handler1.setSuccessor(handler2);
        // 提交请求
        handler1.handleRequest(null);
        System.out.println("----------------------");
        handler1.handleRequest("11");
    }
}

测试
运行Client.java的main()

ConcreteHandler处理请求
----------------------
ConcreteHandler转发请求
ConcreteHandler2处理请求

扩展

纯职责链

  • 每个处理者接收到请求后,要么单纯转发请求,要么单纯处理请求。不允许既处理请求,又转发请求的情况。
  • 请求必须被责任链上的某个处理者处理。不允许出现请求未被处理的情况

不纯职责链

  • 每个处理者接收到请求后,除了单纯转发请求,或者单纯处理请求,还可以
    • 部分处理请求后,转发
    • 完全处理请求后,转发给下个处理者
  • 请求可以不被责任链上的任何处理者处理。

优缺点

优点

  • 遵守“迪米特法则”。请求发送者只负责创建链,不需要知道请求被哪个处理者处理,怎样处理。
  • 遵守“开闭原则”,新增了一个处理者,只需要在客户端中重新建立链即可,原有系统不需要修改。
  • 增强了灵活性。可以在运行时刻对职责链进行动态的增加或者修改。

缺点

  • 请求不一定会被处理。无论是没有可以处理请求的接受者,还是责任链创建错误,都有可能导致请求不被处理。
  • 可能造成死循环。责任链如果是环状的,可能会导致循环调用,造成死循环。

适用环境

  • 有多个对象可以处理一个请求,但只能等运行时才能确定哪个对象处理。
  • 想在不明确指定接受者的情况下,向多个对象中的一个提交请求。
  • 可处理一个请求的对象集合应被动态指定。

使用场景

  • Servlet中的过滤器Filter

扩展

责任链模式和组合模式的联系

责任链模式常和组合模式一起使用。在这种情况下,一个构件的副构件可作为它的后继。

问题

在软件开发中,你在哪里用到了责任链模式?怎么用的?

待补充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值