3责任链模式

责任链模式

责任链模式(Chain of Responsibility Pattern)是一种常见的行为模式。

1责任链模式的定义
责任链的英文原文是:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
意思是:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连城一条链,并沿着这条链传递该请求,知道有对象处理它为止。
责任链的重点是在“链”上,由一条链去处理相似的请求,在链中决定谁来处理这个请求,并返回相应的结果。
责任链模式设计以下两个角色。
  • 抽象处理者角色:该角色队请求进行抽象,并定义一个方法以设定和返回对下一个处理者的引用。
  • 具体处理着角色:该角色接到请求后,可以选择将请求处理掉,或者将请求传给下一处理者。由于具体处理者持有对下一个处理者的引用,因此,如果需要,具体处理者可以访问下一个处理者。
责任链模式类图
创建抽象处理者角色
Handler.java
package com.eric.行为型模式.责任链模式;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 抽象处理者
 * @CreateTime 2020-12-07 18:12:53
 */
public  abstract class Handler {
    private Handler successor;

    //处理方法
    public abstract void handleRequest();
    public Handler getSuccessor(){
        return successor;
    }
    public void setSuccessor(Handler successor)
    {
        this.successor = successor;
    }
}
创建具体处理者角色
ConcreteHandler.java
package com.eric.行为型模式.责任链模式;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 具体的处理者
 * @CreateTime 2020-12-07 18:15:29
 */
public class ConcreteHandler extends Handler {
    //处理请求
    @Override
    public void handleRequest() {
        if(getSuccessor() != null)
        {
            System.out.println("请求传递给"+getSuccessor());
            getSuccessor().handleRequest();
        }else{
            System.out.println("请求处理...");
        }
    }
}
创建测试类
创建h1,h2的实现类,并将h2设置为h1的下一个具体处理者。
Client.java
package com.eric.行为型模式.责任链模式;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 测试类
 * @CreateTime 2020-12-07 18:17:49
 */
public class client {
    public static void main(String[] args) {
        Handler h1 = new ConcreteHandler();
        Handler h2 = new ConcreteHandler();
        h1.setSuccessor(h2);
        h1.handleRequest();
    }
}
测试截图
可以看出h1将业务交给了h2进行处理,h2进行了处理。

2责任链模式的应用
a.责任链模式的优缺点
    责任链模式的优点
    • 责任链模式将请求和处理分开,请求者不知道是谁处理的,处理者可以不用知道请求的全貌。
    • 提高系统灵活性。
    责任链模式的缺点
    • 降低程序的性能,每个请求都是从链头遍历到链尾,当链比较长时,性能会大幅下降。
    • 不易调试,由于采用了类似递归的方式,调试的时候逻辑比较复杂。
注意:责任链中的节点数量需要可控制,避免出现超长链的情况,这就需要设置一个最大的节点数量,超过则不允许增加节点,避免无意识的破坏系统性能。
    
b.责任链模式的应用场景
责任链模式是一种常见的模式,Struts2的核心控件FilterDispatcher是一个Servlet过滤器,该空间就是采用责任链模式在实际项目中使用的比较多,起典型的应用场景如下:
  • 一个请求需要一系列的处理工作。
  • 业务流的处理,如文件审批。
  • 对系统进行补充扩展。

3责任链模式的实例
击鼓传花是一种热闹而紧张的饮酒游戏。酒席上客人依次坐定位置,有一人击鼓,击鼓的地方与传花的地方是分开的,以示公正。开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在某人手中,则该人就需要罚酒。
击鼓传花就是责任链模式的应用。在责任链模式里,很多的对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的那一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态的重新组织链和分配责任。显然,击鼓传花符合责任链模式的定义。参加游戏的人是一个一个具体处理者对象,击鼓的人便是客户端对象。花代表酒令,是传向处理者的请求,每一个参加游戏的人在接到传来的花时,可选择的行为只有两个:将花向下传;或执行酒令喝酒。一个人不能既执行酒令,又向下家传花;当某一个人执行了酒令,游戏重新开始。击鼓的人并不知道最终是由哪一个做游戏的人执行酒令,当然执行酒令的人必然是做游戏中一个。

传花者就是抽象的Handler角色。定义出参加游戏的传花人需要遵守的规则。
具体的传花者是ConcreteHandler角色。每一个传花者都知道下家是谁,或者执行酒令,或者把花向下传;
击鼓者是Client角色,控制游戏的开始和结束。
击鼓传花的类图
创建传花者(抽象处理者)---->制定规则
Player.java
package com.eric.行为型模式.责任链模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 传花者Player的抽象类
 * @CreateTime 2020-12-07 18:56:34
 */
public abstract class Player  {
    private  Player successor;
    public abstract void handle(int i);
    public void setSuccessor(Player successor)
    {
        this.successor = successor;
    }

    //传给下一个
    public void next(int index)
    {
        if(successor != null){
            successor.handle(index);
        }else{
            System.out.println("游戏结束!");
        }
    }
}
创建Player的实现类:PlayerA、PlayerB、PlayerC、PlayerD
PlayerA.java
package com.eric.行为型模式.责任链模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 具体传花者A
 * @CreateTime 2020-12-07 18:59:53
 */
public class PlayerA extends Player {
    //构造函数
    public PlayerA(Player successor){
        this.setSuccessor(successor);
    }
    //实现handle
    @Override
    public void handle(int i) {
        if(i == 1){
            System.out.println("PlayerA 喝酒!");
        }else{
            System.out.println("PlayerA 把花向下传!");
            next(i);
        }
    }
}
PlayerB.java
package com.eric.行为型模式.责任链模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 具体传花者A
 * @CreateTime 2020-12-07 18:59:53
 */
public class PlayerB extends Player {
    //构造函数
    public PlayerB(Player successor){
        this.setSuccessor(successor);
    }
    //实现handle
    @Override
    public void handle(int i) {
        if(i == 2){
            System.out.println("PlayerB 喝酒!");
        }else{
            System.out.println("PlayerB 把花向下传!");
            next(i);
        }
    }
}
PlayerC.java
package com.eric.行为型模式.责任链模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 具体传花者A
 * @CreateTime 2020-12-07 18:59:53
 */
public class PlayerC extends Player {
    //构造函数
    public PlayerC(Player successor){
        this.setSuccessor(successor);
    }
    //实现handle
    @Override
    public void handle(int i) {
        if(i == 3){
            System.out.println("PlayerC 喝酒!");
        }else{
            System.out.println("PlayerC 把花向下传!");
            next(i);
        }
    }
}
PlayerD.java
package com.eric.行为型模式.责任链模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 具体传花者A
 * @CreateTime 2020-12-07 18:59:53
 */
public class PlayerD extends Player {
    //构造函数
    public PlayerD(Player successor){
        this.setSuccessor(successor);
    }
    //实现handle
    @Override
    public void handle(int i) {
        if(i == 4){
            System.out.println("PlayerD 喝酒!");
        }else{
            System.out.println("PlayerD 把花向下传!");
            next(i);
        }
    }
}
创建击鼓者(测试类)
DrumBeater.java
package com.eric.行为型模式.责任链模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 击鼓者
 * @CreateTime 2020-12-07 19:05:10
 */
public class DrumBeater {
    public static void main(String[] args) {
        //创建一个链
        Player player = new PlayerA(new PlayerB(new PlayerC(new PlayerD(null))));
        //击鼓3下停止
        player.handle(3);
    }
}
测试截图






posted @ 2021-05-10 14:23  喵酱张-Eric  阅读(69)  评论(0编辑  收藏  举报