责任链模式

tim-qtp...大约 6 分钟设计模式

什么是责任链模式呢,我们可以举两个生活中的例子来解释一下。

生活实例一:公司报销流程

假设你在公司需要报销一笔费用,报销流程如下:

  1. 部门经理:负责审批小额报销(比如1000元以下)。
  2. 财务主管:负责审批中等金额的报销(比如1000到5000元)。
  3. 总经理:负责审批大额报销(比如5000元以上)。

当你提交报销申请时,申请会先交给部门经理。如果金额在部门经理的权限内,他会直接处理;如果超出权限,他会将申请转交给财务主管。财务主管同样会根据金额决定是否处理,或者继续向上级传递。最终,申请会到达有权限处理的人手中。

这个过程就是一个典型的责任链模式:每个处理者(部门经理、财务主管、总经理)都有机会处理请求,但如果自己无法处理,就会将请求传递给下一个处理者。

Java中的责任链模式

在Java中,责任链模式通过一系列对象(处理者)来处理请求。每个处理者都有一个对下一个处理者的引用。如果当前处理者无法处理请求,它会将请求传递给下一个处理者。

代码实现

我们可以用Java代码来模拟这个报销流程。

// 1. 定义一个抽象处理者类
abstract class Handler {
    protected Handler nextHandler; // 下一个处理者

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(int amount); // 处理请求的方法
}

// 2. 具体处理者:部门经理
class Manager extends Handler {
    @Override
    public void handleRequest(int amount) {
        if (amount <= 1000) {
            System.out.println("部门经理审批通过,报销金额:" + amount);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(amount); // 传递给下一个处理者
        }
    }
}

// 3. 具体处理者:财务主管
class FinanceManager extends Handler {
    @Override
    public void handleRequest(int amount) {
        if (amount > 1000 && amount <= 5000) {
            System.out.println("财务主管审批通过,报销金额:" + amount);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(amount); // 传递给下一个处理者
        }
    }
}

// 4. 具体处理者:总经理
class GeneralManager extends Handler {
    @Override
    public void handleRequest(int amount) {
        if (amount > 5000) {
            System.out.println("总经理审批通过,报销金额:" + amount);
        } else if (nextHandler != null) {
            nextHandler.handleRequest(amount); // 传递给下一个处理者
        }
    }
}

// 5. 测试责任链模式
public class ChainOfResponsibilityDemo {
    public static void main(String[] args) {
        // 创建处理者
        Handler manager = new Manager();
        Handler financeManager = new FinanceManager();
        Handler generalManager = new GeneralManager();

        // 设置责任链
        manager.setNextHandler(financeManager);
        financeManager.setNextHandler(generalManager);

        // 提交报销申请
        manager.handleRequest(800);    // 部门经理处理
        manager.handleRequest(3000);   // 财务主管处理
        manager.handleRequest(10000);  // 总经理处理
    }
}

代码解析

  1. 抽象处理者(Handler):定义了处理请求的接口,并持有下一个处理者的引用。
  2. 具体处理者(Manager、FinanceManager、GeneralManager):实现了处理请求的逻辑。如果自己无法处理,就将请求传递给下一个处理者。
  3. 责任链的构建:通过setNextHandler方法将处理者串联起来,形成一条链。
  4. 请求的处理:从链的第一个处理者开始,依次尝试处理请求,直到有处理者能够处理为止。

输出结果

部门经理审批通过,报销金额:800
财务主管审批通过,报销金额:3000
总经理审批通过,报销金额:10000

生活实例二:请假审批流程

假设在公司中,员工需要请假,通常会经过以下审批流程:

  1. 组长审批:如果请假天数在2天以内,组长可以直接批准。
  2. 经理审批:如果请假天数超过2天但不超过4天,组长将请求转发给经理审批。
  3. 部门领导审批:如果请假天数超过4天但不超过7天,经理将请求转发给部门领导审批。
  4. 总经理审批:如果请假天数超过7天,部门领导将请求转发给总经理审批。

在这个流程中,每个审批人都有自己的审批权限,且审批流程是固定的。 如果某个审批人无法处理请求,他会将请求传递给下一个审批人,直到请求被处理为止。 这正是责任链模式的应用场景。

Java实现示例

以下是使用责任链模式实现上述请假审批流程的Java代码示例:

// 请求类:请假请求
public class LeaveRequest {
    private String employeeName;
    private int leaveDays;

    public LeaveRequest(String employeeName, int leaveDays) {
        this.employeeName = employeeName;
        this.leaveDays = leaveDays;
    }

    public String getEmployeeName() {
        return employeeName;
    }

    public int getLeaveDays() {
        return leaveDays;
    }
}
// 抽象处理者类:审批人
public abstract class Approver {
    protected Approver nextApprover;

    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    public abstract void handleRequest(LeaveRequest request);
}
// 具体处理者类:组长
public class GroupLeader extends Approver {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getLeaveDays() <= 2) {
            System.out.println("组长批准了" + request.getEmployeeName() + "的请假请求,天数:" + request.getLeaveDays());
        } else if (nextApprover != null) {
            nextApprover.handleRequest(request);
        }
    }
}
// 具体处理者类:经理
public class Manager extends Approver {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getLeaveDays() > 2 && request.getLeaveDays() <= 4) {
            System.out.println("经理批准了" + request.getEmployeeName() + "的请假请求,天数:" + request.getLeaveDays());
        } else if (nextApprover != null) {
            nextApprover.handleRequest(request);
        }
    }
}
// 具体处理者类:部门领导
public class DepartmentHead extends Approver {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getLeaveDays() > 4 && request.getLeaveDays() <= 7) {
            System.out.println("部门领导批准了" + request.getEmployeeName() + "的请假请求,天数:" + request.getLeaveDays());
        } else if (nextApprover != null) {
            nextApprover.handleRequest(request);
        }
    }
}
// 具体处理者类:总经理
public class GeneralManager extends Approver {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getLeaveDays() > 7) {
            System.out.println("总经理批准了" + request.getEmployeeName() + "的请假请求,天数:" + request.getLeaveDays());
        } else if (nextApprover != null) {
            nextApprover.handleRequest(request);
        }
    }
}
// 客户端代码:测试责任链模式
public class Client {
    public static void main(String[] args) {
        // 创建具体处理者
        Approver groupLeader = new GroupLeader();
        Approver manager = new Manager();
        Approver departmentHead = new DepartmentHead();
        Approver generalManager = new GeneralManager();

        // 设置责任链
        groupLeader.setNextApprover(manager);
        manager.setNextApprover(departmentHead);
        departmentHead.setNextApprover(generalManager);

        // 创建请假请求
        LeaveRequest request = new LeaveRequest("张三", 5);

        // 开始处理请求
        groupLeader.handleRequest(request);
    }
}

输出结果:

部门领导批准了张三的请假请求,天数:5

在这个示例中,LeaveRequest类表示请假请求,包含员工姓名和请假天数。 Approver是抽象处理者类,定义了处理请求的方法和下一个处理者的引用。 GroupLeaderManagerDepartmentHeadGeneralManager是具体处理者类,分别处理不同天数的请假请求。 Client类用于测试责任链模式的实现。

总结

责任链模式的核心思想是:将请求的发送者和处理者解耦,让多个处理者都有机会处理请求。每个处理者只关心自己能否处理请求,如果不能,就交给下一个处理者。

这种模式非常适合处理像审批流程、过滤器链等场景,能够灵活地扩展和修改处理逻辑。