说明
责任链模式(Chain of Responsibility)使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连城一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
UML
角色:
抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
代码
以张三发起一个请假或加薪的申请为例,审批人有主管,总监,总经理,各自权限不同。
主管:只能处理两天以内的请假请求,其余的转交给上级。
总监:许可一周以内的请假,其余转交给上级。
总经理:所有请假都批准;500以内加薪批准,超出500需要考虑。
此例参考《大话设计模式》,代码如下。
抽象处理者角色
/**
* @author ctl
* @date 2021/1/27
* 管理者
*/
public abstract class Manager {
protected String name;
// 上级
protected Manager superior;
public Manager(String name) {
this.name = name;
}
// 设置上级
public void setSuperior(Manager superior) {
this.superior = superior;
}
// 申请
public abstract void request(Request request);
}
具体处理者角色,主管
/**
* @author ctl
* @date 2021/1/27
* 主管
* 权限:只能处理两天以内的请假请求,其余的转交给上级
*/
public class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
@Override
public void request(Request request) {
if ("请假".equals(request.getRequestType()) && request.getNum() <= 2) {
System.out.println(name + ":" +
request.getRequestContent() +
" 数量" + request.getNum() + " 被批准");
} else {
// 转交上级
if (superior != null) {
superior.request(request);
}
}
}
}
具体处理者角色,总监
/**
* @author ctl
* @date 2021/1/27
* 总监
* 权限:许可一周以内的请假
*/
public class Majordomo extends Manager {
public Majordomo(String name) {
super(name);
}
@Override
public void request(Request request) {
if ("请假".equals(request.getRequestType()) && request.getNum() <= 5) {
System.out.println(name + ":" +
request.getRequestContent() +
" 数量" + request.getNum() + " 被批准");
} else {
// 转交上级
if (superior != null) {
superior.request(request);
}
}
}
}
具体处理者角色,总经理
/**
* @author ctl
* @date 2021/1/27
* 总经理
* 权限:最高级,所有类型的请求都处理
* 请假都批
* 加薪500以下批,否则需要考虑
*/
public class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void request(Request request) {
// 请假 都批准
if ("请假".equals(request.getRequestType())) {
System.out.println(name + ":" +
request.getRequestContent() +
" 数量" + request.getNum() + " 被批准");
} else if ("加薪".equals(request.getRequestType()) && request.getNum() <= 500) {
// 加薪 500以下批准 超过500 考虑考虑
System.out.println(name + ":" +
request.getRequestContent() +
" 数量" + request.getNum() + " 被批准");
} else if ("加薪".equals(request.getRequestType()) && request.getNum() > 500) {
System.out.println(name + ":" +
request.getRequestContent() +
" 数量" + request.getNum() + " 需要考虑考虑");
}
}
}
申请对象,封装了申请内容
/**
* @author ctl
* @date 2021/1/27
* 申请对象
*/
public class Request {
// 申请类型
private String requestType;
// 申请内容
private String requestContent;
// 申请数量
private int num;
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 getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
测试类
/**
* @author ctl
* @date 2021/1/27
*/
public class ChainMain {
public static void main(String[] args) {
CommonManager commonManager = new CommonManager("主管");
Majordomo majordomo = new Majordomo("总监");
GeneralManager generalManager = new GeneralManager("总经理");
// 设置上级,可以按需调整
commonManager.setSuperior(majordomo);
majordomo.setSuperior(generalManager);
// 客户端的每次申请都是由主管发出,内部具体的链路客户端并不知晓
Request request = new Request();
request.setRequestType("请假");
request.setRequestContent("张三请假");
request.setNum(1);
commonManager.request(request);
Request request2 = new Request();
request2.setRequestType("请假");
request2.setRequestContent("张三请假");
request2.setNum(4);
commonManager.request(request2);
Request request3 = new Request();
request3.setRequestType("加薪");
request3.setRequestContent("张三请求加薪");
request3.setNum(500);
commonManager.request(request3);
Request request4 = new Request();
request4.setRequestType("加薪");
request4.setRequestContent("张三请求加薪");
request4.setNum(1000);
commonManager.request(request4);
}
}
结果
张三发起申请,只对接主管,最终根据设定的级别权限,所有角色进行了对应的审批。
总结
责任链模式的好处就是接收者和发送者彼此都不知道对方的角色,而且链中的对象自己也不知道链的结构。大大降低了耦合度。并且可以随时按需修改处理一个请求的结构,增强了给对象指派指责的灵活性。