当前位置: 首页 > news >正文

杂记 - 状态模式 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。
  • 这样实现了请求处理的灵活扩展和解耦。
http://www.jsqmd.com/news/194511/

相关文章:

  • 【干货】Google最新AI Agent报告出炉:小白程序员也能5分钟上手企业级Agent开发!效率直接翻倍,2026年你的工作将被彻底重构!
  • 托盘目标检测数据集VOC+YOLO格式4517张1类别
  • Windows OLE 零点击远程代码执行漏洞(CVE-2025-21298)技术分析与防护
  • 未来已来!Android Studio的AI Agent让编程变得如此简单,开发者:这比antigravity还牛!小白也能秒变大神,不会你就真的out了!
  • geo优化排名系统---内容式生成搜索引擎逻辑开发
  • 吐血推荐8个AI论文工具,助研究生轻松搞定论文写作!
  • 想高薪!0基础怎么转行做AI,2026挑战三个月转行AI大模型岗,需要多久?
  • 笔记本外接屏突然黑屏?我踩了 3 个坑,最后靠回退 N 卡驱动救了急
  • 英语_阅读_Baduanjing_待读
  • PID控制算法十年演进(2015–2025)
  • AI coding 智能体设计系列-03-路径上下文-如何给材料而不喂爆上下文
  • 零基础也能玩转大模型!5分钟带你从入门到精通AI智能体开发,小白程序员直接起飞!
  • 大模型学习路线图:程序员入门到精通(含300集视频教程+免费资源)_大模型学习路线(2026最新)神仙级大模型教程分享
  • CF1202E You Are Given Some Strings...
  • 2026最新银条饰品生产公司top5推荐,湖南郴州等地优质工厂/供货商解析及选择指南 - 全局中转站
  • 2026最新洗衣片工厂top5推荐榜,广东广州等地优质公司及批发源头厂家深度解析/选择指南 - 全局中转站
  • PyBullet十年演进(2015–2025)
  • 2026最新银饰生产公司top5推荐,湖南郴州等地优质工厂/供货商解析及选择指南 - 全局中转站
  • 基于非对称纳什谈判的多微网电能共享运行优化:MATLAB 实现探秘
  • 风光储互补发电系统直流微网:Simulink建模与控制策略探索
  • 卡尔曼滤波十年演进(2015–2025)
  • Nginx 七大应用场景(附配置)
  • 从T5到Sentence-BERT:打造下一代个性化推荐系统 - EmbSum深度解析
  • 开源与AI技术民主化:打破垄断的未来
  • AI 把内容做成了 “泔水”,但你的 “人味儿” 正在变贵
  • [转]Nginx 五大绝技:深入解剖与最佳实践
  • 盒马鲜生礼品卡回收有哪些方法?把睡大觉的闲置卡变成零花钱 - 京顺回收
  • 计算机毕业设计,基于springboot的高校心理教育辅导系统,附源码+数据库+论文+开题,包远程安装调试运行
  • 构造数列【牛客tracker 每日一题】
  • C进阶专题:数据的存储