设计模式之责任链模式
概括
有时会遇到这样的情况,一个请求有多个请求处理者,每个请求处理者的权限不同,我们要用请求到每个处理者挨个请求,这样就造成的代码之间的巨大耦合度
可以把每个请求处理者,以链式的方式串接起来,我们只需要请求第一个处理者,第一个处理者处理不了,由当前处理者把请求转到下一个处理者,直到请求处理完成
这样我们不需要关注请求处理的具体过程,也大大减小了客户端与多个处理器之间的耦合度
这就是责任链模式,也叫职责链模式
结构
- 客户:创建处理器链,并向链头发起请求
- 抽象处理器:处理器的父接口或抽象类,声名链下一个处理器对象(类似链表的形式),并声明处理方法,
- 具体处理器:重写处理器方法,如果当前处理器可以处理,则处理;否则调用下一个处理器的处理方法(可以抽取到抽象处理器中)
例子
请假:员工发出请假请求,每个领导的权限不同,允许批假的天数不同,组长可以批1天以内,经理可以批3天以内,总经理可以批7天以内,
如果请假天数超过7天,不批假
- 请求对象:请假条
- 用来在处理器链中传递请求
public class LeaveRequest {
// 请假人
private String name;
// 请假天数
private Integer day;
// 请假理由
private String content;
// constructor
// getter
// setter
}
- 抽象处理器
public abstract class Handler {
public static final int NUM_ONE = 1;
public static final int NUM_THERE = 3;
public static final int NUM_SEVEN = 7;
protected int numStart;
protected int numEnd;
/**
* 处理链,下一个
*/
protected Handler nextHandler;
public Handler(int numStart, int numEnd) {
this.numStart = numStart;
this.numEnd = numEnd;
}
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 每个子处理器的单独 逻辑
*/
protected abstract void HandlerLeave(LeaveRequest leaveRequest);
/**
* 处理器的公共逻辑
*/
public void submit(LeaveRequest leaveRequest) {
// 如果请假的天数 小于 当前最大的处理天数, 处理
// TODO 当前处理器可以处理
if (leaveRequest.getDay() <= this.numEnd) {
// 执行每个 子处理器 的 单独逻辑
this.HandlerLeave(leaveRequest);
System.out.println("处理完成");
} else {
// TODO 【核心】 当前处理器不能处理
// 如果有下一个,执行链,让下一个处理
if (this.nextHandler != null) {
this.nextHandler.submit(leaveRequest);
} else {
// 走到 责任链 尽头
System.out.println("不批假");
System.out.println("处理失败");
}
}
}
}
- 具体处理器
public class GroupLeader extends Handler{
public GroupLeader() {
super(0, Handler.NUM_ONE);
}
@Override
protected void HandlerLeave(LeaveRequest leaveRequest) {
System.out.println("请假人:" + leaveRequest.getName());
System.out.println("请假时间:" + leaveRequest.getDay());
System.out.println("请假原因:" + leaveRequest.getContent());
System.out.println(this.getClass().getSimpleName() + " 请假批准");
}
}
public class GeneralMagager extends Handler{
public GeneralMagager() {
super(Handler.NUM_THERE, Handler.NUM_SEVEN);
}
@Override
protected void HandlerLeave(LeaveRequest leaveRequest) {
System.out.println("请假人:" + leaveRequest.getName());
System.out.println("请假时间:" + leaveRequest.getDay());
System.out.println("请假原因:" + leaveRequest.getContent());
System.out.println(this.getClass().getSimpleName() + " 请假批准");
}
}
public class Manager extends Handler{
public Manager() {
super(Handler.NUM_ONE, Handler.NUM_THERE);
}
@Override
protected void HandlerLeave(LeaveRequest leaveRequest) {
System.out.println("请假人:" + leaveRequest.getName());
System.out.println("请假时间:" + leaveRequest.getDay());
System.out.println("请假原因:" + leaveRequest.getContent());
System.out.println(this.getClass().getSimpleName() + " 请假批准");
}
}
- 客户端
- 创建处理器链
- 向链头发出请求
public class Client {
public static void main(String[] args) {
// 创建请假条
LeaveRequest leaveRequest = new LeaveRequest("张三", 1, "因病");
// 创建责任链
GroupLeader groupLeader = new GroupLeader();
Manager manager = new Manager();
GeneralMagager generalMagager = new GeneralMagager();
// 设置链条
groupLeader.setNextHandler(manager);
manager.setNextHandler(generalMagager);
// 请假提交,向链头发出请求
groupLeader.submit(leaveRequest);
}
}
模拟Filter过滤器
public interface Request {
}
public interface Response {
}
/**
* 抽象处理器
*/
public interface Filter {
void doFilter(Request req, Response resp, FilterChain chain);
}
- 具体处理器
public class Filter01 implements Filter{
@Override
public void doFilter(Request req, Response resp, FilterChain chain) {
System.out.println(this.getClass().getSimpleName() + "之前...");
chain.doFilter(req, resp);
System.out.println(this.getClass().getSimpleName() + "之后...");
}
}
public class Filter02 implements Filter{
@Override
public void doFilter(Request req, Response resp, FilterChain chain) {
System.out.println(this.getClass().getSimpleName() + "之前...");
chain.doFilter(req, resp);
System.out.println(this.getClass().getSimpleName() + "之后...");
}
}
- 过滤器链
/**
* 过滤器链
*/
public class FilterChain {
// 所有的具体处理器
List<Filter> chain = new ArrayList<>();
// 调用下标
private int index = 0;
// 过滤器链中添加过滤器
public FilterChain addFilter(Filter filter) {
chain.add(filter);
// 方便链式调用
return this;
}
public void doFilter(Request req, Response resp) {
if (index == chain.size()) {
return;
}
Filter filter = chain.get(index);
// 在下次调用之前 下标自增
index++;
filter.doFilter(req, resp, this);
}
}
- 客户端
public class Client {
public static void main(String[] args) {
FilterChain filterChain = new FilterChain();
Filter01 filter01 = new Filter01();
Filter02 filter02 = new Filter02();
// 创建过滤器链
filterChain.addFilter(filter01).addFilter(filter02);
Request req = null;
Response resp = null;
filterChain.doFilter(req, resp);
}
}
- 运行结果
Filter01之前…
Filter02之前…
Filter02之后…
Filter01之后…
责任链的优缺点
- 优点
- 降低客户端与处理器之前的耦合度
- 增加可扩展性,只需添加新的处理器并实现抽象处理器接口,客户连接链
- 单一职责
- 缺点
- 不能保证请求一定处理
- 系统性能会受到一定影响
- 增加的客户端的复杂度,可能会出现循环调用等