首页 > 代码库 > 请求的链式处理——责任链模式

请求的链式处理——责任链模式

什么是责任链模式

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

链上的每个对象都是请求处理者。职责链模式能够将请求的处理者组织成一条链。并让请求沿着链传递,由链上的处理者对请求进行对应的处理,client无须关心请求的处理细节以及请求的传递,仅仅需将请求发送到链上就可以,实现请求发送者和请求处理者解耦。

职责链模式定义例如以下:

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

职责链模式结构的核心在于引入了一个抽象处理者。

职责链模式结构如图所看到的:

技术分享

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

● Handler(抽象处理者):它定义了一个处理请求的接口,一般设计为抽象类,因为不同的详细处理者处理请求的方式不同,因此在当中定义了抽象请求处理方法。因为每个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个抽象处理者类型的对象(如结构图中的successor),作为其对下家的引用。

通过该引用。处理者能够连成一条链。

● ConcreteHandler(详细处理者):它是抽象处理者的子类。能够处理用户请求,在详细处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前须要进行推断,看是否有对应的处理权限。假设能够处理请求就处理它,否则将请求转发给后继者;在详细处理者中能够訪问链中下一个对象,以便请求的转发。

在职责链模式里,非常多对象由每个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。

发出这个请求的client并不知道链上的哪一个对象终于处理这个请求。这使得系统能够在不影响client的情况下动态地又一次组织链和分配责任。

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

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

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

    public abstract void handleRequest(String request);
}

上述代码中。抽象处理者类定义了对下家的引用对象,以便将请求转发给下家,该对象的訪问符可设为protected。在其子类中能够使用。

在抽象处理者类中声明了抽象的请求处理方法,详细实现交由子类完毕。

详细处理者是抽象处理者的子类,它具有两大作用:第一是处理请求。不同的详细处理者以不同的形式实现抽象请求处理方法handleRequest();第二是转发请求,假设该请求超出了当前处理者类的权限,能够将该请求转发给下家。

详细处理者类的典型代码例如以下:

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

在详细处理类中通过对请求进行推断能够做出对应的处理。

须要注意的是。职责链模式并不创建职责链,职责链的创建工作必须由系统的其它部分来完毕。通常是在使用该职责链的client中创建职责链。职责链模式减少了请求的发送端和接收端之间的耦合。使多个对象都有机会处理这个请求。

实战案例

相信大家在公司中或多或少的都经历过报销。普通情况下在公司报销会因报销额度的不同而转为不同人员进行审批。比如组长仅仅能审批1000元、主管仅仅能审批5000元。经理能审批10000元。10000元以上的仅仅能由老板亲自审批了。

我们使用职责链模式来模拟 一下这个审批过程。

首先我们先声明一个抽象的领导类。

public abstract class Leader {

    // 上一级领导处理者
    protected Leader nextHandler; 

    public final void handleRequest(int money) {
        if (money <= limit()) {
            handle(money);
        } else {
            if(null != nextHandler) {
                nextHandler.handle(money);
            }
        }
    }

    /**
     * 自身能批复的额度权限
     * @return 额度
     */
    public abstract int limit();

    /**
     * 处理报账行为
     * @param money 详细金额
     */
    public abstract void handle(int money);
}

在这个抽象的领导类中做了两件事,一是定义了两个抽象接口方法来确定一个领导者应有的行为和属性,而是声明了一个处理报账请求的方法来确定当前领导是否有能力处理报账请求,假设没有权限。则将该请求转发给上级领导处理。接下来是各个领导类的实现。

public class GroupLeader extends Leader {

    @Override
    public int limit() {
        return 1000;
    }

    @Override
    public void handle(int money) {
        System.out.println("组长批复报销 :" + money + "元");
    }

}

public class Director extends Leader {

    @Override
    public int limit() {
        return 5000;
    }

    @Override
    public void handle(int money) {
        System.out.println("主管批复报销" + money + "元");
    }

}

public class Manager extends Leader {

    @Override
    public int limit() {
        return 10000;
    }

    @Override
    public void handle(int money) {
        System.out.println("经理批复报销" + money + "元");
    }

}

public class Boss extends Leader {

    @Override
    public int limit() {
        return Integer.MAX_VALUE;
    }

    @Override
    public void handle(int money) {
        System.out.println("老板批复报销" + money + "元");
    }

}

我们在看看client是怎样发起请求申请报销的。

public static void main(String[] args) {
        // 构造各个领导对象
        GroupLeader groupLeader = new GroupLeader();
        Director director = new Director();
        Manager manager = new Manager();
        Boss boss = new Boss();

        // 设置上一级领导处理对象
        groupLeader.nextHandler = director;
        director.nextHandler = manager;
        manager.nextHandler = boss;

        // 发起报销申请
        groupLeader.handleRequest(10000);
    }

首先我们须要构建各个领导对象,然后将每一级的上级设置好,这样链式就形成了。最后我们申请报销10000元。执行结果例如以下:

主管批复报销10000元

纯与不纯的职责链模式

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

(1) 纯的职责链模式

一个纯的职责链模式要求一个详细处理者对象仅仅能在两个行为中选择一个:要么承担所有责任。要么将责任推给下家,不同意出现某一个详细处理者对象在承担了一部分或所有责任后又将责任向下传递的情况。并且在纯的职责链模式中,要求一个请求必须被某一个处理者对象所接收,不能出现某个请求未被不论什么一个处理者对象处理的情况。在前面的採购单审批实例中应用的是纯的职责链模式。

(2)不纯的职责链模式

在一个不纯的职责链模式中同意某个请求被一个详细处理者部分处理后再向下传递,或者一个详细处理者处理完某请求后其后继处理者能够继续处理该请求,并且一个请求能够终于不被不论什么处理者对象所接收。

职责链模式总结

职责链模式通过建立一条链来组织请求的处理者,请求将沿着链进行传递。请求发送者无须知道请求在何时、何处以及怎样被处理,实现了请求发送者与处理者的解耦。在软件开发中,假设遇到有多个对象能够处理同一请求时能够应用职责链模式,比如在Web应用开发中创建一个过滤器(Filter)链来对请求数据进行过滤,在工作流系统中实现公文的分级审批等等,使用职责链模式能够较好地解决此类问题。

1.主要长处

职责链模式的主要长处例如以下:

(1) 职责链模式使得一个对象无须知道是其它哪一个对象处理其请求,对象仅需知道该请求会被处理就可以,接收者和发送者都没有对方的明白信息。且链中的对象不须要知道链的结构。由client负责链的创建,减少了系统的耦合度。

(2) 请求处理对象仅需维持一个指向其后继者的引用。而不须要维持它对所有的候选处理者的引用,可简化对象的相互连接。

(3) 在给对象分派职责时,职责链能够给我们很多其它的灵活性,能够通过在执行时对该链进行动态的添加或改动来添加或改变处理一个请求的职责。

(4) 在系统中添加一个新的详细请求处理者时无须改动原有系统的代码,仅仅须要在client又一次建链就可以。从这一点来看是符合“开闭原则”的。

2.主要缺点

职责链模式的主要缺点例如以下:

(1) 因为一个请求没有明白的接收者。那么就不能保证它一定会被处理。该请求可能一直到链的末端都得不到处理。一个请求也可能因职责链没有被正确配置而得不到处理。

(2) 对于比較长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,并且在进行代码调试时不太方便。

(3) 假设建链不当。可能会造成循环调用,将导致系统陷入死循环。

3.适用场景

在下面情况下能够考虑使用职责链模式:

(1) 有多个对象能够处理同一个请求,详细哪个对象处理该请求待执行时刻再确定,client仅仅需将请求提交到链上,而无须关心请求的处理对象是谁以及它是怎样处理的。

(2) 在不明白指定接收者的情况下,向多个对象中的一个提交一个请求。

(3) 可动态指定一组对象处理请求。client能够动态创建职责链来处理请求,还能够改变链中处理者之间的先后次序。

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

请求的链式处理——责任链模式