likes
comments
collection
share

深究设计模式之-责任链模式

作者站长头像
站长
· 阅读数 16

继续研究设计模式,责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其主要目的是将请求的发送者和接收者解耦,形成一条责任链。每个处理者都有自己的处理逻辑,可以选择处理请求或将请求传递给下一个处理者。责任链模式常用于处理请求的场景,例如日志记录、审批流程等。

举个生活中请假的例子来说明责任链模式:

假设你是一家公司的员工,需要请假。在这个公司里,员工请假的审批流程是需要经过部门经理、人事部门和总经理的审批。如果你请假的天数不同,审批的责任也会不同。

  1. 首先,你向直属主管提出了 2 天的病假请求。直属主管会先审批,如果符合条件(比如小于等于 2 天),则部门经理会批准这个请假请求。
  2. 如果你请假 5 天,超出了部门经理的审批权限,这时候部门经理会将请求转给部门经理。部门经理审批规定可以请假 5 天以内,所以部门经理会批准这个请求。
  3. 如果你请假 7 天,那么这个请求就会被直接转到总经理那里。总经理的审批权限更高,可以批准更长时间的请假。

责任链模式的好处在于它可以动态地建立处理链,每个处理者只需要关注自己的处理逻辑,将处理请求的责任交给下一个处理者或者结束处理。这样可以提高代码的灵活性和可维护性,同时也能更好地符合实际业务场景中的处理需求。

主要角色:

  1. 处理者(Handler): 定义了处理请求的接口,并持有一个后继者的引用。

  2. 具体处理者(Concrete Handler): 实现了处理者接口,负责处理请求,如果自己无法处理,则将请求传递给下一个处理者。

  3. 客户端(Client): 创建和发送请求的对象。

示例:

用代码实现一下上面这个请假审批的例子,假设有三个领导分别负责不同级别的审批。

package com.luke.designpatterns.chainofResponsibilityPattern;

// 处理者接口
interface Approver {
    void processRequest(LeaveRequest request);
}

// 具体处理者 - 直属主管
class Supervisor implements Approver {
    private Approver successor;

    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 2) {
            System.out.println("直属主管批准了假期");
        } else if (successor != null) {
            System.out.println("请假时间超过2天,直属主管无权批准");
            successor.processRequest(request);
        }
    }

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

// 具体处理者 - 部门经理
class Manager implements Approver {
    private Approver successor;

    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 5) {
            System.out.println("部门经理批准了假期");
        } else if (successor != null) {
            System.out.println("请假时间超过5天,部门经理无权批准");
            successor.processRequest(request);
        }
    }

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

// 具体处理者 - 总经理
class GeneralManager implements Approver {

    @Override
    public void processRequest(LeaveRequest request) {
        System.out.println("总经理批准了假期");
    }
}

// 请假请求类
class LeaveRequest {
    private int days;

    public LeaveRequest(int days) {
        this.days = days;
    }

    public int getDays() {
        return days;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Supervisor supervisor = new Supervisor();
        Manager manager = new Manager();
        Approver generalManager = new GeneralManager();

        // 构建责任链
        supervisor.setSuccessor(manager);
        manager.setSuccessor(generalManager);

        // 发送请假请求
        LeaveRequest request1 = new LeaveRequest(1);
        LeaveRequest request3 = new LeaveRequest(3);
        LeaveRequest request7 = new LeaveRequest(7);
        System.out.println("请一天假");
        supervisor.processRequest(request1);
        System.out.println("请三天假");
        supervisor.processRequest(request3);
        System.out.println("请七天假");
        supervisor.processRequest(request7);
    }
}

深究设计模式之-责任链模式

在这个例子中,Approver 是处理者接口,SupervisorManagerGeneralManager 是具体处理者。客户端代码通过创建责任链,并将请求传递给责任链的头部,从而实现请求的处理。每个具体处理者根据自己的处理逻辑决定是否处理请求,如果不能处理,则将请求传递给下一个处理者。责任链模式使得请求的发送者和接收者解耦,可以灵活地调整责任链的结构和顺序。

适用场景

责任链模式在以下场景中非常适用:

  1. 请求需要被多个对象处理:当一个请求需要被多个对象依次处理时,责任链模式就非常合适。比如,一个请求可能需要经过多个级别的管理者或者多个部门的审批。
  2. 请求的处理顺序不确定或可变:责任链模式允许你灵活地定义处理请求的顺序,甚至在运行时动态改变这个顺序。
  3. 避免发送者与接收者之间的耦合:发送者不需要知道请求将由哪个接收者处理,而接收者也不需要知道请求的发送者是谁。这种松耦合的设计有助于系统的维护和扩展。
  4. 需要动态添加或移除处理器:责任链模式允许你在运行时添加或移除处理器,这样可以很方便地调整处理流程,而不需要修改已有的代码。
  5. 减少重复的条件判断:责任链模式可以将复杂的条件判断逻辑分散到各个处理器中,使得每个处理器只需要关注自己能处理的情况,简化了代码的逻辑结构。