ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java 责任链模式实战:基于 java-design-patterns 仓库的请求处理链完整解析

Java 责任链模式实战:基于 java-design-patterns 仓库的请求处理链完整解析 示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载导读责任链Chain of Responsibility是 Gang of Four 提出的经典行为型设计模式之一其核心价值在于将请求的发送者与接收者解耦允许多个对象依次获得处理请求的机会请求沿着链条传递直到被某个合适的处理器接收。本文以 java-design-patterns 仓库中chain-of-responsibility模块源码位于 chain-of-responsibility/src/main/java/com/iluwatar/chain为蓝本结合官方阿拉伯语文档 localization/ar/chain-of-responsibility/README.md 的核心内容从模式意图、代码实现、类图结构、适用场景到优缺点与关联模式带你完整掌握责任链模式在 Java 中的落地写法。读完本文你将能够独立实现一套可动态调整处理顺序、按需增加处理器的请求分发机制。模式概览责任链是什么其他名称责任链模式在不同资料中也被称为命令链Chain of Command对象链Chain of Objects责任链Responsibility Chain模式意图责任链模式通过给予多个对象处理请求的机会将请求发送者与其接收者解耦。接收对象被串联成一条链请求沿着链传递直到某个对象将其处理完毕。发送者无需知道谁会处理请求只需发出请求即可。现实世界类比文档给出了一个生动的例子兽人国王Orc King大声向军队下达命令离他最近的、依次响应的是指挥官Commander、军官Officer与士兵Soldier。指挥官、军官、士兵共同构成了一条责任链——每条命令沿链传递直到找到能处理它的那个人。用简单的话说该模式帮助构建一条对象链请求从一端进入从一个对象流转到另一个对象直到遇到合适的处理器为止。权威定义在面向对象设计中责任链模式由一组命令对象源和一系列处理对象组成。每个处理对象都包含定义其可处理命令类型的逻辑无法处理的请求则被传递给链中的下一个处理对象。程序化示例兽人军团的请求处理链本仓库中chain-of-responsibility模块用兽人国王下达命令、军团分级响应的故事演示了该模式共包含 8 个 Java 文件。下面按职责逐一拆解。第一步请求载体Request与RequestType请求对象封装了被传递的信息其源码见 Request.javaGetter public class Request { private final RequestType requestType; private final String requestDescription; private boolean handled; public Request(final RequestType requestType, final String requestDescription) { this.requestType Objects.requireNonNull(requestType); this.requestDescription Objects.requireNonNull(requestDescription); } public void markHandled() { this.handled true; } Override public String toString() { return getRequestDescription(); } }要点说明requestType请求类型链上每个处理器通过它判断自己是否能够处理该请求requestDescription请求描述文本同时作为toString()的返回值便于日志输出handled与markHandled()记录请求是否已被处理。源码注释明确说明该状态只能从未处理单向变为已处理不存在撤销处理的路径构造器通过Objects.requireNonNull强制要求类型与描述非空避免空指针隐患。请求类型定义在 RequestType.javapublic enum RequestType { DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX }本示例只有三种请求保卫城堡、拷问囚犯、征收赋税。第二步处理器抽象RequestHandler所有处理器实现统一接口 RequestHandler.java接口定义了四个方法public interface RequestHandler { boolean canHandleRequest(Request req); int getPriority(); void handle(Request req); String name(); }方法职责canHandleRequest(Request)判断当前处理器是否有能力处理该请求getPriority()返回处理优先级用于决定链中调用顺序handle(Request)实际执行处理逻辑name()返回处理器名称用于日志输出第三步三个具体处理器指挥官 OrcCommander.java 只处理保卫城堡类请求Slf4j public class OrcCommander implements RequestHandler { Override public boolean canHandleRequest(Request req) { return req.getRequestType() RequestType.DEFEND_CASTLE; } Override public int getPriority() { return 2; } Override public void handle(Request req) { req.markHandled(); LOGGER.info({} handling request \{}\, name(), req); } Override public String name() { return Orc commander; } }军官 OrcOfficer.java 与士兵 OrcSoldier.java 的定义方式与指挥官完全一致只是处理对象和元数据不同三者配置对比如下处理器可处理的请求类型优先级名称OrcCommanderDEFEND_CASTLE2Orc commanderOrcOfficerTORTURE_PRISONER3Orc officerOrcSoldierCOLLECT_TAX1Orc soldier三个类均通过 Lombok 的Slf4j注解获得LOGGER并在handle()中先调用req.markHandled()标记请求已处理再输出日志。第四步组装链条OrcKing国王 OrcKing.java 负责构建链条并发起请求public class OrcKing { private ListRequestHandler handlers; public OrcKing() { buildChain(); } private void buildChain() { handlers Arrays.asList(new OrcCommander(), new OrcOfficer(), new OrcSoldier()); } public void makeRequest(Request req) { handlers .stream() .sorted(Comparator.comparing(RequestHandler::getPriority)) .filter(handler - handler.canHandleRequest(req)) .findFirst() .ifPresent(handler - handler.handle(req)); } }请求分发逻辑可以拆解为四步流水线buildChain()将三个处理器放入ListRequestHandler完成链条组装sorted(...)按getPriority()升序排列确保处理顺序可控filter(...)过滤出所有有能力处理该请求的处理器findFirst().ifPresent(...)取第一个符合条件的处理器执行handle()。需要特别指出的是从源码结构看本实现并未采用经典责任链每个处理器持有下一个处理器引用的链表式写法而是由OrcKing统一持有处理器列表通过优先级排序 能力过滤 取首个的方式完成请求路由达到的效果与责任链一致——发送者不知道也不关心最终由谁处理。第五步运行演示与输出程序入口 App.java 演示了完整调用var king new OrcKing(); king.makeRequest(new Request(RequestType.DEFEND_CASTLE, defend castle)); king.makeRequest(new Request(RequestType.TORTURE_PRISONER, torture prisoner)); king.makeRequest(new Request(RequestType.COLLECT_TAX, collect tax));控制台输出Orc commander handling request defend castle Orc officer handling request torture prisoner Orc soldier handling request collect tax三种不同类型的请求分别被链条中对应的处理器接收全程无需在调用方指定接收者。类图结构OrcKing.java 持有RequestHandler列表三个具体处理器实现RequestHandler接口Request依赖RequestType整体结构如下图所示图片来源 chain-of-responsibility/etc/chain-of-responsibility.urm.png其 PlantUML 源文件见 chain-of-responsibility/etc/chain-of-responsibility.urm.puml责任链模式类图OrcKing 持有 RequestHandler 列表OrcCommander、OrcOfficer、OrcSoldier 实现 RequestHandler 接口源码级实现细节与测试验证测试用例印证请求必被处理模块配套的单元测试 OrcKingTest.java 覆盖了所有请求类型断言国王发出的每一个请求最终都被标记为已处理class OrcKingTest { private static final ListRequest REQUESTS List.of( new Request(RequestType.DEFEND_CASTLE, Dont let the barbarians enter my castle!!), new Request(RequestType.TORTURE_PRISONER, Dont just stand there, tickle him!), new Request(RequestType.COLLECT_TAX, Dont steal, the King hates competition ...)); Test void testMakeRequest() { final var king new OrcKing(); REQUESTS.forEach(request - { king.makeRequest(request); assertTrue(request.isHandled(), Expected all requests from King to be handled, but [ request ] was not!); }); } }该测试验证了责任链的核心承诺只要链条中存在能处理该请求的处理器请求就不会丢失且测试中的三类请求恰好与三个处理器一一对应。模式在仓库中的定位模块分类Behavioral行为型模式核心标签Gang of Four、Decoupling解耦、Event-driven、Messaging模块完整英文文档见 chain-of-responsibility/README.md阿拉伯语译文即本文所依托的 localization/ar/chain-of-responsibility/README.md。何时使用责任链模式根据官方文档当出现以下情况时应考虑使用责任链模式多个对象都可能处理同一个请求且处理器无法预先确定——应让系统自动判定由谁处理希望向若干对象中的某一个发出请求但不想显式指定接收者能够处理请求的对象集合需要动态确定例如运行时增删处理器或调整顺序。反之如果链条很长且结构复杂导致流程难以追踪或需要严格保证每个请求都有处理结果则需要谨慎评估是否引入兜底处理器。现实世界中的典型应用责任链模式在主流框架中随处可见文档列举了以下典型场景GUI 框架中的事件冒泡一个事件可能在 UI 组件层级的多层中被处理中间件框架请求依次穿过一串处理对象日志框架消息可经过一串 Logger每个 Logger 以不同方式处理java.util.logging.Logger#log()日志记录按级别沿 logger 层级向上传递Apache Commons Chain基于责任链思想的通用链式处理框架javax.servlet.Filter#doFilter()Servlet 过滤器链每个 Filter 处理后调用chain.doFilter()将请求传给下一个是责任链模式的教科书级应用。优点与代价优点降低耦合请求发送者无需知道具体由哪个处理器处理请求职责分配更灵活可以通过改变链条成员与排列顺序增删或调整对请求的处理责任支持默认处理器当链中没有具体处理器能处理请求时可以设置一个兜底的默认处理器。代价调试与理解成本高当链条又长又复杂时追踪请求的流转路径会比较困难请求可能无人处理如果链条中没有全捕获catch-all处理器请求可能最终处于未处理状态存在性能开销请求可能经过多个处理器才能命中目标甚至遍历整条链仍找不到处理器。与其他模式的关系责任链模式常与其他行为型/结构型模式配合使用本仓库中对应的模式模块可作为对照学习材料命令模式可将请求封装为对象再沿责任链传递组合模式责任链常与组合模式结合使用例如 UI 组件树与事件冒泡装饰器模式装饰器可以像责任链中的职责一样串联使用。参考资料官方文档引用的经典著作如下可作为深入学习的延伸阅读Design Patterns: Elements of Reusable Object-Oriented SoftwareGoF 四人组原著Head First Design PatternsPattern-Oriented Software Architecture, Volume 1: A System of PatternsRefactoring to PatternsPattern Languages of Program Design 3小结通过本仓库chain-of-responsibility模块我们完整走通了责任链模式的意图 → 建模 → 实现 → 测试 → 应用全链路Request封装请求状态RequestHandler统一处理器契约OrcCommander/OrcOfficer/OrcSoldier各司其职OrcKing负责组装链条并按优先级路由请求。这套结构清晰、可测试、可动态调整的实现可直接迁移到中间件、过滤器、事件分发等真实业务场景中。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐责任链模式Chain of Responsibility实战指南基于 java-design-patterns 仓库构建可扩展的请求处理链责任链模式Chain of Responsibility实战指南基于 java design patterns 仓库构建可扩展的请求处理链 导读 本文以示例工程教程责任链模式Chain of Responsibility实战解析Java 设计模式中的请求处理链责任链模式Chain of Responsibility实战解析Java 设计模式中的请求处理链 责任链Chain of Responsibility示例工程教程Fluent Interface 模式实战用 Java 方法链构建可读的流式 APIjava-design-patterns 仓库解析Fluent Interface 模式实战用 Java 方法链构建可读的流式 APIjava design patterns 仓库解析 Fluent In示例工程教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表