news 2026/5/1 5:11:09

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
杂记 - 状态模式 VS. 责任链模式

目录

    • 一、总体对比
    • 二、状态模式
    • 三、责任链模式
    • 四、扩展:手撸Java WebFilter实现

一、总体对比

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

对比项状态模式责任链模式
意图允许对象在内部状态改变时改变它的行为,
看起来就像改变了其类。
使多个对象都有机会处理请求,将这些对象连成一条链,
并沿着这条链传递请求,直到有对象处理它为止。
结构通常有一个上下文(Context)对象和多个状态(State)对象。
上下文持有当前状态的引用,行为委托给当前状态对象。
有一个处理者接口,每个处理者持有下一个处理者的引用。
请求沿链传递,直到被处理。
应用场景对象的行为依赖于它的状态,
并且在运行时可能根据状态变化而改变行为。
有多个对象可以处理同一个请求,
具体由谁处理在运行时决定。
示例工作流引擎、订单状态流转、TCP连接状态。Java Web Filter、日志处理链、审批流。
总结状态模式关注“对象状态的切换”,
每个状态封装一组行为,状态切换时行为也随之切换。
状态模式强调“同一个对象在不同状态下的行为变化”。
责任链模式关注“请求的传递”,
每个处理者决定是否处理请求或传递给下一个处理者。
责任链模式强调“多个对象对同一请求的处理机会”。

二、状态模式

类图:

Client

Context

- state: State

+ request()

«interface»

State

+ handle(Context)

ConcreteStateA

+ handle(Context)

ConcreteStateB

+ handle(Context)

示例代码:

publicinterfaceState{voidhandle(Contextcontext);}publicclassConcreteStateAimplementsState{@Overridepublicvoidhandle(Contextcontext){System.out.println("当前状态:A,切换到B");context.setState(newConcreteStateB());}}publicclassConcreteStateBimplementsState{@Overridepublicvoidhandle(Contextcontext){System.out.println("当前状态:B,切换到A");context.setState(newConcreteStateA());}}publicclassContext{privateStatestate;publicContext(Statestate){this.state=state;}publicvoidsetState(Statestate){this.state=state;}publicvoidrequest(){if(state!=null){state.handle(this);}}}publicclassClient{publicstaticvoidmain(String[]args){Contextcontext=newContext(newConcreteStateA());context.request();// A -> Bcontext.request();// B -> A}}

三、责任链模式

类图:

next

Client

«abstract»

Handler

+setNext(Handler)

+handleRequest(Request)

ConcreteHandlerA

+handleRequest(Request)

ConcreteHandlerB

+handleRequest(Request)

示例代码:

publicabstractclassHandler{protectedHandlernext;publicvoidsetNext(Handlernext){this.next=next;}publicabstractvoidhandleRequest(Stringrequest);}publicclassConcreteHandlerAextendsHandler{@OverridepublicvoidhandleRequest(Stringrequest){if("A".equals(request)){System.out.println("ConcreteHandlerA 处理请求: "+request);}elseif(next!=null){next.handleRequest(request);}else{System.out.println("请求未被处理: "+request);}}}publicclassConcreteHandlerBextendsHandler{@OverridepublicvoidhandleRequest(Stringrequest){if("B".equals(request)){System.out.println("ConcreteHandlerB 处理请求: "+request);}elseif(next!=null){next.handleRequest(request);}else{System.out.println("请求未被处理: "+request);}}}publicclassClient{publicstaticvoidmain(String[]args){HandlerhandlerA=newConcreteHandlerA();HandlerhandlerB=newConcreteHandlerB();handlerA.setNext(handlerB);handlerA.handleRequest("A");// ConcreteHandlerA 处理请求: AhandlerA.handleRequest("B");// ConcreteHandlerB 处理请求: BhandlerA.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 实现:

// MyFilter.javaimportjavax.servlet.*;importjava.io.IOException;publicclassMyFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{// 前置处理System.out.println("MyFilter 前置处理");// 传递给下一个 Filter 或 Servletchain.doFilter(request,response);// 后置处理System.out.println("MyFilter 后置处理");}}

责任链模式简化实现(模拟 FilterChain):

// Filter.javapublicinterfaceFilter{voiddoFilter(Requestrequest,Responseresponse,FilterChainchain);}// FilterChain.javaimportjava.util.List;publicclassFilterChain{privateList<Filter>filters;privateintindex=0;publicFilterChain(List<Filter>filters){this.filters=filters;}publicvoiddoFilter(Requestrequest,Responseresponse){if(index<filters.size()){filters.get(index++).doFilter(request,response,this);}else{// 最终处理(如Servlet)System.out.println("到达最终处理(Servlet)");}}}// Request.java / Response.javapublicclassRequest{}publicclassResponse{}

使用链式调用:

// Main.javaimportjava.util.Arrays;publicclassMain{publicstaticvoidmain(String[]args){Filterfilter1=(req,res,chain)->{System.out.println("Filter1 前置");chain.doFilter(req,res);System.out.println("Filter1 后置");};Filterfilter2=(req,res,chain)->{System.out.println("Filter2 前置");chain.doFilter(req,res);System.out.println("Filter2 后置");};FilterChainchain=newFilterChain(Arrays.asList(filter1,filter2));chain.doFilter(newRequest(),newResponse());}}

输出示例:

Filter1 前置 Filter2 前置 到达最终处理(Servlet) Filter2 后置 Filter1 后置

总结:

  • Filter 链式调用本质是责任链模式的应用。
  • 每个 Filter 处理完后通过chain.doFilter传递给下一个 Filter 或最终 Servlet。
  • 这样实现了请求处理的灵活扩展和解耦。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 4:49:07

springboot+vue基于spring的药品销售商城进销存管理系统的设计与实现

目录摘要技术要点开发技术核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 该系统基于SpringBoot和Vue.js技…

作者头像 李华
网站建设 2026/5/1 1:41:27

springboot+vue社区居民信息流动人口管户籍理及数据分析与可视化系统设计

目录 摘要 开发技术 核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 摘要 该系统基于SpringBoot后端框架与Vue…

作者头像 李华
网站建设 2026/4/30 10:06:24

openJiuwen 0 基础入门:工作流编排从零到一及深度踩坑指南

openJiuwen 0 基础入门&#xff1a;工作流编排从零到一及深度踩坑指南、 前言&#xff1a;什么是工作流&#xff1f; 在接触 openJiuwen 之前&#xff0c;我对“工作流”&#xff08;Workflow&#xff09;这个概念几乎一无所知。听起来像是企业级系统里的高深术语&#xff0c;…

作者头像 李华
网站建设 2026/5/1 4:47:13

Gemini CLI 终极使用指南

1. 简介&#xff1a;为什么使用 Gemini CLI&#xff1f;Gemini CLI (google/gemini-cli) 是 Google 推出的开源命令行 AI 代理。它不仅是一个聊天机器人&#xff0c;更是一个能通过终端理解你项目上下文、读取文件甚至执行任务的开发助手。主要特点&#xff1a;上下文感知&…

作者头像 李华
网站建设 2026/5/1 4:41:21

极限编程(ExtremeProgramming)是什么?

极限编程&#xff08;ExtremeProgramming&#xff09;是什么&#xff1f; 极限编程&#xff08;ExtremeProgramming&#xff09;&#xff0c;简称 XP&#xff0c;是一种敏捷软件开发框架&#xff0c;它强调软件质量和响应变化的能力&#xff0c;尤其适用于需求快速变化或存在不…

作者头像 李华