简介
责任链模式(Chain of Responsibility Pattern)使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
实例
责任链模式包含一下角色:
Handler
: 抽象处理者。定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。ConcreteHandler
:具体处理者。具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。Client
:客户类
下面我们以一个简单的请假作为示例。假设请假一天,项目经理处理就能处理,三天之类归项目总监处理,七天内归老板处理,请假不允许超过七天。 抽象处理者
public abstract class AbstractHandler {
/**
* 下一个处理对象
*/
private AbstractHandler next;
/**
* 处理请假
*
* @param leaveDays 天数
* @return 处理结果
*/
public final String handleLeave(int leaveDays) {
if (this.getLeaveDays() >= leaveDays) {
return this.handle();
} else {
if (Objects.nonNull(next)) {
return next.handleLeave(leaveDays);
} else {
return "大老板都不能处理你的假期了~~";
}
}
}
/**
* 具体处理
*
* @return 处理结果
*/
protected abstract String handle();
/**
* 每个处理类能处理的天数,数据可以使数据库获取,这里简单就写死了
*
* @return 请假天数
*/
protected abstract Integer getLeaveDays();
/**
* 设置下一个处理类
*
* @param next
*/
public void setNext(AbstractHandler next) {
this.next = next;
}
}
具体处理者
// 项目经理处理
public class PMHandler extends AbstractHandler {
@Override
protected String handle() {
return "你的请假被项目经理处理了";
}
@Override
protected Integer getLeaveDays() {
return 1;
}
}
// 项目总监处理
public class PDHandler extends AbstractHandler {
@Override
protected String handle() {
return "你的请假被项目总监处理了";
}
@Override
protected Integer getLeaveDays() {
return 3;
}
}
// 大老板处理
public class BossHandler extends AbstractHandler {
@Override
protected String handle() {
return "你的请假被大老板处理了";
}
@Override
protected Integer getLeaveDays() {
return 7;
}
}
客户端
@Test
public void test() {
PMHandler pmHandler = new PMHandler();
PDHandler pdHandler = new PDHandler();
BossHandler bossHandler = new BossHandler();
pmHandler.setNext(pdHandler);
pdHandler.setNext(bossHandler);
String leaveRes = pmHandler.handleLeave(1);
System.out.println(leaveRes);
String leaveRes1 = pmHandler.handleLeave(3);
System.out.println(leaveRes1);
String leaveRes2 = pmHandler.handleLeave(7);
System.out.println(leaveRes2);
String leaveRes3 = pmHandler.handleLeave(8);
System.out.println(leaveRes3);
}
类图
优点
- 降低耦合度。它将请求的发送者和接收者解耦;
- 简化了对象。使得对象不需要知道链的结构;
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任;
- 增加新的请求处理类很方便。
缺点
- 请求没有明确的接收者,不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;
- 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
适用场景
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定;
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
- 可动态指定一组对象处理请求。
总结
责任链模式有两种使用形式:纯责任链模式和不纯的责任链模式。
如果一个类要么承担责任处理请求要么将请求踢给下一个皮球,则被称为纯责任链模式;如果一个类承担了一部分责任,还将请求踢给下一个皮球,则被称为不纯的责任链模式。纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。