设计模式之责任链模式

本文参考:

https://www.cnblogs.com/aeolian/p/8888958.html

https://www.cnblogs.com/fengyumeng/p/10839570.html

定义

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

责任链模式英文原话是: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 object and pass the request along the chain until an object handles it.

翻译:使多个对象都有处理请求的机会,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象串成一条链,并沿着这条链一直传递该请求,直到有对象处理它为止。

责任链模式的重点在“链上”,由一条链去处理相似的请求,在链中决定谁来处理这个请求,并返回相应的结果。

角色:

抽象处理者(Handler)角色:该角色对请求进行抽象,并定义一个方法来设定和返回对下一个处理者的引用。

具体处理者(Concrete Handler):该角色接到请求后,可以选择将请求处理掉,或者将请求传给下一个处理者。由于具体处理者持有对下一个处理者的引用,因此,如果需要,处理者可以访问下一个处理者。

简单实例

如果在公司里,因为病假要请一个月的假需要经过组长、经理等好几轮的审核签字,这跟咱们的责任链模式非常相似,现以请假为例:

         角色1:请假条,其实可以理解成请假人,因为请假条上自然有请假人信息。

  角色2:领导人,小组长、部门经理、总经理都是审批人。

  动作:领导人审批请假条。

流程如下:

请假条抽象:

public interface ILeave {
    String getName();//请假人姓名
    int getNum();//请假天数
    String getContent();//请假条内容
}

请假条实现:

public class Leave implements ILeave{
    private String name;//姓名
    private int num;//请假天数
    private String content;//请假内容

    public Leave(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }

    public String getContent() {
        return content;
    }
}

领导人抽象:

public interface IHandler {
    void handleLeave(ILeave leave);//处理请假条
}

领导人实现:

public class GroupLeader implements IHandler {
    @Override
    public void handleLeave(ILeave leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("小组长审批:同意。");
    }
}
public class Manager implements IHandler {
    @Override
    public void handleLeave(ILeave leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("部门经理审批:同意。");
    }
}
public class BigManager implements IHandler {
    @Override
    public void handleLeave(ILeave leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("总经理审批:同意。");
    }
}

客户端实现:

public static void main(String[] args) {
        //请假条来一张
        ILeave leave = new Leave("小花",5,"身体不适");

        //小组长第一个审批
        IHandler groupLeader = new GroupLeader();
        groupLeader.handleLeave(leave);

        if(leave.getNum() >= 3){
            IHandler manager = new Manager();
            manager.handleLeave(leave);
        }
        if(leave.getNum() >= 7){
            IHandler bigManager = new BigManager();
            bigManager.handleLeave(leave);
        }
    }

输出:

小花请假5天,身体不适。
小组长审批:同意。
小花请假5天,身体不适。
部门经理审批:同意。

这个程序是有问题,如果公司修改请假制度,一个月以上的请假需要老板审核签字,就得在客户端实现方法再写个if语句,这显然是有问题的。正确的逻辑应该是什么样的呢? 应该是小花递了请假条之后,就只需要等结果即可,而不是找了这个审批,回来后又跑去找那个审批。

优化:

请假条抽象:

public interface ILeave {
    String getName();//请假人姓名
    int getNum();//请假天数
    String getContent();//请假条内容
}

请假条:

public class Leave implements ILeave{
    private String name;//姓名
    private int num;//请假天数
    private String content;//请假内容

    public Leave(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }

    public String getContent() {
        return content;
    }
}

领导人抽象:

public abstract class Handler {
    protected final static int NUM_ONE = 1;
    protected final static int NUM_THREE = 3;
    protected final static int NUM_SEVEN = 7;

    //该领导处理的请假天数区间
    private int numStart = 0;
    private int numEnd = 0;

    //领导上面还有领导
    private Handler nextHandler;

    //设置请假天数范围 上不封顶
    public Handler(int numStart) {
        this.numStart = numStart;
    }

    //设置请假天数范围
    public Handler(int numStart, int numEnd) {
        this.numStart = numStart;
        this.numEnd = numEnd;
    }

    //设置上级领导
    public void setNextHandler(Handler nextHandler){
        this.nextHandler = nextHandler;
    }

    //提交请假条
    public final void submit(ILeave leave){
        if(0 == this.numStart){
            return;
        }

        //如果请假天数达到该领导者的处理要求
        if(leave.getNum() >= this.numStart){
            this.handleLeave(leave);

            //如果还有上级 并且请假天数超过了当前领导的处理范围
            if(null != this.nextHandler && leave.getNum() > numEnd){
                this.nextHandler.submit(leave);//继续提交
            }
        }
    }

    //各级领导处理请假条方法
    protected abstract void handleLeave(ILeave leave);
}

领导人实例:

public class GroupLeader extends Handler {

    public GroupLeader() {
        //小组长处理1-3天的请假
        super(Handler.NUM_ONE, Handler.NUM_THREE);
    }

    @Override
    protected void handleLeave(ILeave leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("小组长审批:同意。");
    }
}
public class Manager extends Handler {
    public Manager() {
        //部门经理处理3-7天的请假
        super(Handler.NUM_THREE, Handler.NUM_SEVEN);
    }

    @Override
    protected void handleLeave(ILeave leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("部门经理审批:同意。");
    }
}
public class BigManager extends Handler {
    public BigManager() {
        //部门经理处理7天以上的请假
        super(Handler.NUM_SEVEN);
    }

    @Override
    protected void handleLeave(ILeave leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("总经理审批:同意。");
    }
}

客户端:

public static void main(String[] args) {
        //请假条来一张
        ILeave leave = new Leave("小花",5,"身体不适");

        //各位领导
        Handler groupLeader = new GroupLeader();
        Handler manager = new Manager();
        Handler bigManager = new BigManager();

        groupLeader.setNextHandler(manager);//小组长的领导是部门经理
        manager.setNextHandler(bigManager);//部门经理的领导是总经理
        //之所以在这里设置上级领导,是因为可以根据实际需求来更改设置,如果实战中上级领导人都是固定的,则可以移到领导实现类中。

        //提交申请
        groupLeader.submit(leave);
    }

输出:

小花请假5天,身体不适。
小组长审批:同意。
小花请假5天,身体不适。
部门经理审批:同意。

优点

  • 责任链模式将请求和处理分开,请求者不知道是谁处理的,处理者可以不用知道请求的全貌。
  • 提高系统的灵活性。

缺点

  • 降低程序的性能。每个请求都是从链头遍历到链尾,当链比较长的时候,性能会大幅下降。
  • 不易于调试。由于该模式采用了类似递归的方式,调试的时候逻辑比较复杂。

应用场景

责任链模式是一种常见的模式,Struts2的核心控件FilterDispatcher是一个Servlet过滤器,该控件就是采用责任链模式,可以对用户请求进行层层过滤处理。责任链模式在实际项目中的使用比较多,其典型的应用场景如下:

  • 一个请求需要一系列的处理工作。
  • 业务流的处理,例如文件审批。
  • 对系统进行扩展补充。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值