责任链模式

110 阅读3分钟

定义

用于解决请求的传递与处理问题,通过将请求沿着一条由多个对象连接起来的责任链进行传递,每个对象负责处理特定类型或范围的请求,直到请求被某个对象处理或者到达链的末端为止。这种模式允许在不明确指定接收者的情况下,将一个请求连同相应的处理程序动态地链接在一起。

优缺点

优点:

  1. 解耦:发送者无需直到请求的具体接收者是谁,使得系统更易于扩展和修改
  2. 灵活:可以动态地改变责任链的结构,例如添加新的处理者或重新排列现有处理者的顺序
  3. 减少代码量:避免了过多的 if-else 或 switch-case 语句,简化了对象间的通信逻辑

缺点:

  1. 调试困难:由于请求时链式传递的,定位错误可能会变得复杂。
  2. 性能开销:如果责任链过长,且每次请求都要经过所有处理者,可能造成不必要的性能损耗。
  3. 循环依赖:如果没有正确管理链的结构,可能导致循环传递的情况。

结构图和示例

  • Handler类(抽象处理者):定义了一个处理请求的接口,并且包含对下一个处理者的引用,这样可以将请求传递给下一个处理者。同时,提供了一个方法来设置下一个处理者。
  • Concretehandler类(具体处理者):实现了抽象处理者的接口,能够处理特定类型的请求。当接受到一个请求时,如果能够处理则执行相应操作;如果不能处理,则将请求转发给它的后继处理者。
/**
 * 需要处理的申请
 */
public class Request {
    // 申请类型
    private String requestType;
    // 申请内容
    private String requestContent;
    // 数量
    private int number;

    public String getRequestType() {
        return requestType;
    }

    public void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public String getRequestContent() {
        return requestContent;
    }

    public void setRequestContent(String requestContent) {
        this.requestContent = requestContent;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }
}
/**
 * 管理者抽象类
 */
public abstract class Manager {
    // 姓名
    String name;
    // 管理者的上级
    Manager superior;

    public Manager(String name) {
        this.name = name;
    }

    public void setSuperior(Manager superior) {
        this.superior = superior;
    }

    // 处理申请
    public abstract void requestApplications(Request request);
}

/**
 * 经理
 */
public class CommonManager extends Manager {
    public CommonManager(String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType().equals("请假") && request.getNumber() <= 2) {
            System.out.printf("%s : %s 数量 %s 被批准\n", name, request.getRequestContent(), request.getNumber());
        } else {
            if (superior != null) {
                superior.requestApplications(request);
            }
        }
    }
}
/**
 * 总监
 */
public class Majordomo extends Manager {

    public Majordomo(String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType().equals("请假") && request.getNumber() <= 5) {
            System.out.printf("%s : %s 数量 %s 被批准\n", name, request.getRequestContent(), request.getNumber());
        } else {
            if (superior != null) {
                superior.requestApplications(request);
            }
        }
    }
}

/**
 * 总经理
 */
public class GeneralManager extends Manager {
    public GeneralManager(String name) {
        super(name);
    }

    @Override
    public void requestApplications(Request request) {
        if (request.getRequestType().equals("请假")) {
            System.out.printf("%s : %s 数量 %s 被批准\n", name, request.getRequestContent(), request.getNumber());
        } else if (request.getRequestType().equals("加薪")) {
            if (request.getNumber() <= 500) {
                System.out.printf("%s : %s 数量 %s 被批准\n", name, request.getRequestContent(), request.getNumber());
            } else {
                System.out.printf("%s : %s 数量 %s 再说吧\n", name, request.getRequestContent(), request.getNumber());
            }
        }
    }
}

/**
 * 测试
 */
public class Test {
    public static void main(String[] args) {
        CommonManager jinli = new CommonManager("金利");
        Majordomo zongjian = new Majordomo("宗剑");
        GeneralManager zhongjingli = new GeneralManager("钟精励");

        jinli.setSuperior(zongjian);
        zongjian.setSuperior(zhongjingli);

        Request request = new Request();
        request.setRequestType("请假");
        request.setRequestContent("Gerry请假");
        request.setNumber(1);
        jinli.requestApplications(request);

        request.setNumber(4);
        jinli.requestApplications(request);

        request.setNumber(6);
        jinli.requestApplications(request);

        Request request2 = new Request();
        request2.setRequestType("加薪");
        request2.setRequestContent("Gerry加薪");
        request2.setNumber(500);
        jinli.requestApplications(request2);

        request2.setNumber(1000);
        jinli.requestApplications(request2);
    }
}