目录
一、总体对比
状态模式和责任链模式都是行为型设计模式,但它们的意图和应用场景不同:
| 对比项 | 状态模式 | 责任链模式 |
|---|---|---|
| 意图 | 允许对象在内部状态改变时改变它的行为, 看起来就像改变了其类。 | 使多个对象都有机会处理请求,将这些对象连成一条链, 并沿着这条链传递请求,直到有对象处理它为止。 |
| 结构 | 通常有一个上下文(Context)对象和多个状态(State)对象。 上下文持有当前状态的引用,行为委托给当前状态对象。 | 有一个处理者接口,每个处理者持有下一个处理者的引用。 请求沿链传递,直到被处理。 |
| 应用场景 | 对象的行为依赖于它的状态, 并且在运行时可能根据状态变化而改变行为。 | 有多个对象可以处理同一个请求, 具体由谁处理在运行时决定。 |
| 示例 | 工作流引擎、订单状态流转、TCP连接状态。 | Java Web Filter、日志处理链、审批流。 |
| 总结 | 状态模式关注"对象状态的切换", 每个状态封装一组行为,状态切换时行为也随之切换。 状态模式强调"同一个对象在不同状态下的行为变化"。 | 责任链模式关注"请求的传递", 每个处理者决定是否处理请求或传递给下一个处理者。 责任链模式强调"多个对象对同一请求的处理机会"。 |
二、状态模式
类图:
Client
Context
- state: State
- request()
<<interface>>
State - handle(Context)
ConcreteStateA - handle(Context)
ConcreteStateB - handle(Context)
示例代码:
java
public interface State {
void handle(Context context);
}
public class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("当前状态:A,切换到B");
context.setState(new ConcreteStateB());
}
}
public class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("当前状态:B,切换到A");
context.setState(new ConcreteStateA());
}
}
public class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
if (state != null) {
state.handle(this);
}
}
}
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStateA());
context.request(); // A -> B
context.request(); // B -> A
}
}
三、责任链模式
类图:
next
Client
<<abstract>>
Handler
+setNext(Handler)
+handleRequest(Request)
ConcreteHandlerA
+handleRequest(Request)
ConcreteHandlerB
+handleRequest(Request)
示例代码:
java
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(String request);
}
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(String request) {
if ("A".equals(request)) {
System.out.println("ConcreteHandlerA 处理请求: " + request);
} else if (next != null) {
next.handleRequest(request);
} else {
System.out.println("请求未被处理: " + request);
}
}
}
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(String request) {
if ("B".equals(request)) {
System.out.println("ConcreteHandlerB 处理请求: " + request);
} else if (next != null) {
next.handleRequest(request);
} else {
System.out.println("请求未被处理: " + request);
}
}
}
public class Client {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNext(handlerB);
handlerA.handleRequest("A"); // ConcreteHandlerA 处理请求: A
handlerA.handleRequest("B"); // ConcreteHandlerB 处理请求: B
handlerA.handleRequest("C"); // 请求未被处理: C
}
}
两者本质区别:
状态模式是"状态驱动行为",责任链模式是"链式传递请求"。
四、扩展:手撸Java WebFilter实现
Java WebFilter 链式调用的实现原理是基于"责任链模式"(Chain of Responsibility Pattern)。每个 Filter 处理请求后,可以选择继续传递给下一个 Filter 或终止链路。Filter 链由容器(如 Tomcat)维护,依次调用每个 Filter 的 doFilter 方法,最后到达目标 Servlet。
原理简述:
- 每个 Filter 通过
doFilter(ServletRequest, ServletResponse, FilterChain)方法接收请求。 FilterChain负责调用下一个 Filter 或最终的 Servlet。- 责任链模式:每个处理者(Filter)持有对下一个处理者(FilterChain)的引用。
示例代码:
自定义 Filter 实现:
java
// MyFilter.java
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 前置处理
System.out.println("MyFilter 前置处理");
// 传递给下一个 Filter 或 Servlet
chain.doFilter(request, response);
// 后置处理
System.out.println("MyFilter 后置处理");
}
}
责任链模式简化实现(模拟 FilterChain):
java
// Filter.java
public interface Filter {
void doFilter(Request request, Response response, FilterChain chain);
}
// FilterChain.java
import java.util.List;
public class FilterChain {
private List<Filter> filters;
private int index = 0;
public FilterChain(List<Filter> filters) {
this.filters = filters;
}
public void doFilter(Request request, Response response) {
if (index < filters.size()) {
filters.get(index++).doFilter(request, response, this);
} else {
// 最终处理(如Servlet)
System.out.println("到达最终处理(Servlet)");
}
}
}
// Request.java / Response.java
public class Request {}
public class Response {}
使用链式调用:
java
// Main.java
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Filter filter1 = (req, res, chain) -> {
System.out.println("Filter1 前置");
chain.doFilter(req, res);
System.out.println("Filter1 后置");
};
Filter filter2 = (req, res, chain) -> {
System.out.println("Filter2 前置");
chain.doFilter(req, res);
System.out.println("Filter2 后置");
};
FilterChain chain = new FilterChain(Arrays.asList(filter1, filter2));
chain.doFilter(new Request(), new Response());
}
}
输出示例:
Filter1 前置
Filter2 前置
到达最终处理(Servlet)
Filter2 后置
Filter1 后置
总结:
- Filter 链式调用本质是责任链模式的应用。
- 每个 Filter 处理完后通过
chain.doFilter传递给下一个 Filter 或最终 Servlet。 - 这样实现了请求处理的灵活扩展和解耦。