杂记 - 状态模式 VS. 责任链模式

目录

一、总体对比

状态模式和责任链模式都是行为型设计模式,但它们的意图和应用场景不同:

对比项 状态模式 责任链模式
意图 允许对象在内部状态改变时改变它的行为, 看起来就像改变了其类。 使多个对象都有机会处理请求,将这些对象连成一条链, 并沿着这条链传递请求,直到有对象处理它为止。
结构 通常有一个上下文(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。
  • 这样实现了请求处理的灵活扩展和解耦。
相关推荐
JavaBoy_XJ14 小时前
行为型-状态模式
状态模式
星盾网安1 天前
智慧门店系统开发-06-新嘉丽WF质保录入功能实现
状态模式
小北方城市网2 天前
GEO 新生态:跨界融合 + 场景渗透,重构 AI 时代本地商业增长版图
大数据·网络·人工智能·python·状态模式
小园子的小菜2 天前
Token自动续期技术方案全解析:原理、优缺点与生产实践
java·后端·架构·状态模式
小北方城市网3 天前
第 4 课:前端工程化进阶 ——Vue 核心语法 + 组件化开发(前端能力质的飞跃)
大数据·开发语言·数据库·python·状态模式·数据库架构
山风wind4 天前
Spring中责任链模式的工业级应用简单剖析
java·spring·责任链模式
山风wind4 天前
设计模式-责任链模式:让请求在链条中流动直到被处理
设计模式·责任链模式
山风wind5 天前
设计模式:状态模式详解-让对象的行为随状态改变而改变
设计模式·状态模式
hdsoft_huge5 天前
Java 实现高效查询海量 geometry 及 Protobuf 序列化与天地图前端分片加载
java·前端·状态模式