目录
说明
- 行为型模式之一,其他还有命令模式、模板方法模式、访问者模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、迭代器模式
-
职责链模式(Chain of Responsibility Pattern), 又叫责任链模式,为请求创建了一个 接收者对象的链(简单示意图)。这种模式对请求的发送者和接收者进行解耦
-
职责链模式通常 每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推
实现方式
“老板,我想加薪。”
“没问题,我先问问老总。”
“。。。”
“老板,我想请假。”
“没问题,批了。”
“啊这”
/**
* 职责链模式(使多个对象都有机会处理请求。将对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止)
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/23
*/
public class ChainOfResponsibilityTest {
public static void main(String[] args) {
Manager commonManger = new CommonManger("普通经理小明");
Manager generalManager = new GeneralManager("总经理王总");
// 设置上级关系
commonManger.setSuperior(generalManager);
Request askForLeaveRequest = new Request();
askForLeaveRequest.setRequestType("请假");
askForLeaveRequest.setRequestContent("程序员小红申请请假一天");
// 申请由普通经理发起,但具体谁决策,客户端并不知道
commonManger.requestApplication(askForLeaveRequest);
Request raiseRequest = new Request();
raiseRequest.setRequestType("加薪");
raiseRequest.setRequestContent("程序员小刚申请加薪500");
commonManger.requestApplication(raiseRequest);
}
}
/**
* 抽象的管理者类(Handler)
* <p>
*
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-24
*/
abstract class Manager {
private String name;
public Manager(String name) {
this.name = name;
}
/**
* 上级
*/
private Manager superior;
/**
* 处理请求
* <p>
*
* @param request
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
public abstract void requestApplication(Request request);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Manager getSuperior() {
return superior;
}
public void setSuperior(Manager superior) {
this.superior = superior;
}
}
/**
* 普通经理(ConcreteHandler1)
* <p>
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/24
*/
class CommonManger extends Manager {
private static String ASK_FOR_LEAVE = "请假";
public CommonManger(String name) {
super(name);
}
/**
* 处理请求
* <p>
*
* @param request
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void requestApplication(Request request) {
if (ASK_FOR_LEAVE.equals(request.getRequestType())) {
System.out.println(getName() + "批准" + request.getRequestContent());
} else {
if (getSuperior() != null) {
// 其余的申请交由上级处理
getSuperior().requestApplication(request);
}
}
}
}
/**
* 总经理(ConcreteHandler2)
* <p>
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/24
*/
class GeneralManager extends Manager {
private static String RAISE = "加薪";
public GeneralManager(String name) {
super(name);
}
/**
* 处理请求
* <p>
*
* @param request
* @author : ZRH
* @version : 1.0.0
* @date : 2020-07-23
*/
@Override
public void requestApplication(Request request) {
if (RAISE.equals(request.getRequestType())) {
System.out.println(getName() + "批准" + request.getRequestContent());
} else {
System.out.println(request.getRequestType() + "要再考虑");
}
}
}
/**
* 申请
* <p>
*
* @author ZRH
* @version 1.0.0
* @date 2020/7/24
*/
class Request {
/**
* 申请的类型
*/
private String requestType;
/**
* 申请的内容
*/
private String requestContent;
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;
}
}
优点
- 将请求和处理分开,实现解耦,提高系统的灵活性
- 简化了对象,使对象不需要知道链的结构
缺点
- 性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在Handler中设置一个最大节点数量,在setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能
- 调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂
应用场景
-
多级请求
-
请假 / 加薪等审批流程
-
Java Web 中 Tomcat 对 Encoding 的处理
-
拦截器