本文字数:3964字,阅读大约需要 12 分钟。
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象按照顺序处理请求,并且每个对象可以选择自己是否处理该请求或将其传递给下一个对象。这种模式将请求的发送者和接收者解耦,同时提供了更大的灵活性和可扩展性。
责任链模式通过将多个处理请求的对象组成一条链,使请求在链上传递,直到有一个对象处理它为止。每个处理对象都负责判断自己能否处理该请求,如果可以则进行处理,否则将请求传递给下一个处理对象。这样,请求发送者无需知道具体的处理对象,只需将请求发送到责任链上即可。
责任链模式包含以下角色:
通过责任链模式,我们可以动态地组合处理对象,灵活地配置处理流程,这种解耦使得系统更加灵活和可扩展。
责任链模式常用于以下场景:
常见的实际应用场景包括:
责任链模式在这些场景中可以减少代码的耦合性,提高代码的可维护性和可扩展性。
优点:
缺点:
在实际应用中,我们需要根据具体情况评估责任链模式的优缺点,并合理地选择使用或者改进这个模式。
要实现责任链模式,我们按照以下步骤进行:
以下是一个简单的示例,演示如何使用责任链模式处理请假申请:
步骤一:定义处理者接口(Handler)
/**
* <p>
* 责任链模式——抽象类处理器
* </p>
*/
public abstract class AbstractHandler {
/**
* 责任链中的下一个元素
*/
protected AbstractHandler nextHandler;
public AbstractHandler setNextChain(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
return nextHandler;
}
/**
* 责任链处理逻辑
*/
public void linkChain(LeaveRequest request) {
handler(request);
//这里还可以加入其他方法
if (Objects.nonNull(nextHandler)) {
nextHandler.linkChain(request);
}
}
/**
* 抽象方法
*/
protected abstract void handler(LeaveRequest request);
}
请求对象为:
@Getter
public class LeaveRequest {
private final String employee;
private final int days;
public LeaveRequest(String employee, int days) {
this.employee = employee;
this.days = days;
}
}
步骤二:实现具体处理者类(ConcreteHandler)
@Slf4j
public class Handler1 extends AbstractHandler {
@Override
public void handler(LeaveRequest request) {
if (request.getDays() <= 3) {
log.info("ConcreteHandlerA 处理了 " + request.getEmployee() + " 的请假申请,天数为:" + request.getDays());
}
}
}
@Slf4j
public class Handler2 extends AbstractHandler {
@Override
public void handler(LeaveRequest request) {
if (request.getDays() > 3 && request.getDays() <= 7) {
log.info("ConcreteHandlerB 处理了 " + request.getEmployee() + " 的请假申请,天数为:" + request.getDays());
}
}
}
@Slf4j
public class Handler3 extends AbstractHandler {
@Override
protected void handler(LeaveRequest request) {
if (request.getDays() > 7) {
log.info("ConcreteHandlerC 处理了 " + request.getEmployee() + " 的请假申请,天数为:" + request.getDays());
}
}
}
步骤三:在客户端代码中创建责任链,并将请求发送到责任链上的第一个处理者
public class ChainPatternDemo {
private static AbstractHandler getChainOfHandler() {
AbstractHandler handler1 = new Handler1();
AbstractHandler handler2 = new Handler2();
AbstractHandler handler3 = new Handler3();
//可以自定义链路顺序
handler1.setNextChain(handler2).setNextChain(handler3);
return handler1;
}
public static void main(String[] args) {
AbstractHandler chain = getChainOfHandler();
LeaveRequest request1 = new LeaveRequest("张三", 2);
chain.linkChain(request1);
LeaveRequest request2 = new LeaveRequest("李四", 5);
chain.linkChain(request2);
LeaveRequest request3 = new LeaveRequest("王五", 10);
chain.linkChain(request3);
}
}
在上述示例中,我们定义了三个具体处理者类:Handler1
、Handler2
和Handler3
,它们分别处理请假申请。客户端代码创建了责任链,并将请求发送给第一个处理者Handler1
。每个具体处理者判断自己是否能够处理该请求,如果可以则进行处理,否则传递给下一个处理者。
运行以上代码,输出结果为:
ConcreteHandlerA 处理了 张三 的请假申请,天数为:2
ConcreteHandlerB 处理了 李四 的请假申请,天数为:5
ConcreteHandlerC 处理了 王五 的请假申请,天数为:10
这只是一个简单示例,实际使用时可以根据业务需求进行适当的扩展和修改。
在使用责任链模式时,需要注意以下几点:
setNextChain()
方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能。我们可以通过建造者模式来创建责任链中的处理者对象。这种优化可以使责任链的创建和配置更加灵活和可拓展,符合开闭原则。
优化后的示例代码:
/**
* <p>
* 责任链模式——抽象类处理器
* </p>
*/
public abstract class AbstractHandler {
/**
* 责任链中的下一个元素
*/
protected AbstractHandler nextHandler;
private void setNextChain(AbstractHandler nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 责任链处理逻辑
*/
public void linkChain(LeaveRequest request) {
handler(request);
//这里还可以加入其他方法
if (Objects.nonNull(nextHandler)) {
nextHandler.linkChain(request);
}
}
/**
* 抽象方法
*/
protected abstract void handler(LeaveRequest request);
public static class Builder {
private AbstractHandler head;
private AbstractHandler tail;
public Builder addHandler(AbstractHandler handler) {
if (this.head == null) {
this.head = this.tail = handler;
return this;
}
this.tail.setNextChain(handler);
this.tail = handler;
return this;
}
public AbstractHandler build() {
return this.head;
}
}
}
public class ChainPatternDemo {
private static AbstractHandler getChainOfHandler() {
return new AbstractHandler.Builder()
.addHandler(new Handler1())
.addHandler(new Handler2())
.addHandler(new Handler3())
.build();
}
public static void main(String[] args) {
AbstractHandler chain = getChainOfHandler();
LeaveRequest request1 = new LeaveRequest("张三", 2);
chain.linkChain(request1);
LeaveRequest request2 = new LeaveRequest("李四", 5);
chain.linkChain(request2);
LeaveRequest request3 = new LeaveRequest("王五", 10);
chain.linkChain(request3);
}
}
在客户端代码中,我们使用建造者模式创建了一个包含多个处理者的责任链,并发送了一个请假申请。责任链会按照添加处理者的顺序依次处理请假申请,直到找到能够处理该请求的处理者为止。
通过调用 addHandler
方法,我们可以逐步构建责任链,将处理者添加到责任链的末尾,由于 setNextChain()
不对外调用,作用域可以更改为 private
,最后,通过调用 build
方法,我们可以获取责任链的起始处理者。
Spring中我们可以使用 @Component
,@Order
注解,来让容器帮我们自动构建责任链,从而简化代码。
public abstract class Handler {
abstract void handler(LeaveRequest request);
}
@Order(value = 1)
@Component
@Slf4j
public class HandlerA extends Handler{
@Override
public void handler(LeaveRequest request) {
if (request.getDays() <= 3) {
log.info("ConcreteHandlerA 处理了 " + request.getEmployee() + " 的请假申请,天数为:" + request.getDays());
}
}
}
@Order(value = 2)
@Component
@Slf4j
public class HandlerB extends Handler {
@Override
public void handler(LeaveRequest request) {
if (request.getDays() > 3 && request.getDays() <= 7) {
log.info("ConcreteHandlerB 处理了 " + request.getEmployee() + " 的请假申请,天数为:" + request.getDays());
}
}
}
@Order(value = 3)
@Component
@Slf4j
public class HandlerC extends Handler{
@Override
public void handler(LeaveRequest request) {
if (request.getDays() > 7) {
log.info("ConcreteHandlerC 处理了 " + request.getEmployee() + " 的请假申请,天数为:" + request.getDays());
}
}
}
测试:
@Test
public void test() {
for (Handler handler : handlerChain) {
LeaveRequest request = new LeaveRequest("王五", 10);
handler.handler(request);
}
}
输出:
ConcreteHandlerC 处理了 王五 的请假申请,天数为:10
这种写法有其利弊,优点是可以避免繁琐的责任链构建过程,简化了代码结构;缺点是具体处理者类之间的执行顺序不够直观,具体使用时需要权衡考虑。
责任链模式的优点在于其低耦合性、灵活性和可扩展性,使得我们能够更加轻松地管理和组织复杂的处理流程。然而,也要注意其缺点,即请求未必被处理和对处理顺序敏感的特点。
最重要的是,在实际应用中根据具体需求合理运用责任链模式,结合其他设计模式,以便在代码结构和可维护性上取得更好的效果。
点在看,让更多看见。
·················END·················