代码改变世界

职责链模式(Chain of Responsibility Pattern)——请求的链式处理

说明:设计模式系列文章是读刘伟所著《设计模式的艺术之道(软件开发人员内功修炼之道)》一书的阅读笔记。个人感觉这本书讲的不错,有兴趣推荐读一读。详细内容也可以看看此书作者的博客https://blog.csdn.net/LoveLion/article/details/17517213

“一对二”,“过”,“过”……这声音熟悉吗?你会想到什么?

对!纸牌。在类似“斗地主”这样的纸牌游戏中,某人出牌给他的下家,下家看看手中的牌,如果要不起上家的牌则将出牌请求再转发给他的下家,其下家再进行判断。

一个循环下来,如果其他人都要不起该牌,则最初的出牌者可以打出新的牌。

在这个过程中,牌作为一个请求沿着一条链在传递,每一位纸牌的玩家都可以处理该请求。

在设计模式中,我们也有一种专门用于处理这种请求链式传递的模式,它就是本章将要介绍的职责链模式。

模式概述

很多情况下,在一个软件系统中可以处理某个请求的对象不止一个。

职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。

链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿着链传递,由链上的处理者对请求进行相应的处理。

客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,实现请求发送者和请求处理者解耦。

模式定义

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

模式结构图

职责链模式结构的核心在于引入了一个抽象处理者。职责链模式结构如下图所示:

在职责链模式结构图中包含如下几个角色:

  • Handler(抽象处理者)

它定义了一个处理请求的接口,一般设计为抽象类,由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。因为每一个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个抽象处理者类型的对象(如结构图中的successor),作为其对下家的引用。通过该引用,处理者可以连成一条链。

  • ConcreteHandler(具体处理者)

它是抽象处理者的子类,可以处理用户请求,在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者;在具体处理者中可以访问链中下一个对象,以便请求的转发。

模式伪代码

在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。

请求在这个链上传递,直到链上的某一个对象决定处理此请求。

发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

职责链模式的核心在于抽象处理者类的设计,抽象处理者的典型代码如下所示:

public abstract class Handler {
    // 维持对下家的引用
    protected Handler successor;

    // 抽象处理请求的方法
    public abstract void handleRequest(Object request);
}

public class ConcreteHandler extends Handler {
    @Override
    public void handleRequest(Object request) {
        if (请求满足条件) {
            // 处理请求
        } else {
            // 转发请求
            this.successor.handleRequest(request);
        }
    }
}

注意,创建职责链伪代码这里没有写。其实很简单,先创建这些具体的处理器对象,然后依次把这些处理器对象串起来。

职责链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求。

纯与不纯的职责链模式

职责链模式可分为纯的职责链模式和不纯的职责链模式两种:

  • 纯的职责链模式

一个纯的职责链模式要求一个具体处理者对象只能在两个行为中选择一个:要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或全部责任后又将责任向下传递的情况。

而且在纯的职责链模式中,要求一个请求必须被某一个处理者对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况。

  • 不纯的职责链模式

在一个不纯的职责链模式中允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某请求后其后继处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收。

模式总结

职责链模式通过建立一条链来组织请求的处理者,请求将沿着链进行传递,请求发送者无须知道请求在何时、何处以及如何被处理,实现了请求发送者与处理者的解耦。

在软件开发中,如果遇到有多个对象可以处理同一请求时可以应用职责链模式,例如在Web应用开发中创建一个过滤器(Filter)链来对请求数据进行过滤,在工作流系统中实现公文的分级审批等等,使用职责链模式可以较好地解决此类问题。

适用场景

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  • 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序。
posted @ 2021-11-01 16:23  行无际  阅读(153)  评论(0编辑  收藏  举报