尧图精选

java-design-patterns 中的 Delegation 委托模式:Java 运行时动态任务委托的权威实践指南

🕒 发布时间:2026/10/1 17:57:15 📁 来源:尧图网络
示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载导读本文围绕开源仓库 java-design-patterns 中 Delegation委托模式 展开系统讲解如何让一个对象对外表现某种行为、却把实际执行责任动态委派给另一个关联对象从而在不依赖继承的前提下实现基于组合的复用。你将通过仓库中真实的Printer打印示例掌握委托模式的接口设计、委托控制器Delegator与具体实现Delegate的协作关系、运行时切换行为的用法以及它的适用场景、优缺点和与 Proxy、Strategy、Composite 等模式的关系。模式概览也被称为代理Proxy模式委托模式Delegation Pattern在传统命名中也常被称为代理模式Proxy Pattern属于结构型Structural设计模式核心标签是解耦Decoupling。它描述了一种协作方式对象对外「声称」自己能完成某项行为但实际上把执行责任**委托delegate**给另一个与之关联的对象。调用方只需要面对一个统一的外观无需关心真正干活的类是谁。目标Intent委托模式的根本目标可以概括为一句话让一个对象对外的表现与真实执行相分离——对象可以表达某个行为但将该行为的实现责任转交给另一个关联对象去完成。这一机制带来的直接收益是降低类与自身方法的耦合度使行为可以在运行时被动态替换。真实世界例子冒险者与武器文档中给出了一个非常直观的现实类比想象一群冒险者他们根据各自的技能与能力使用不同的武器与怪物战斗。我们需要能够为他们配备不同武器而无需修改每一种武器的源码。委托模式正是通过把工作动态委托给一个实现相关接口的特定对象来实现这一点。在这个例子中「冒险者」扮演委托方Delegator「武器」扮演被委托方Delegate。冒险者并不亲自实现「攻击」的细节而是把攻击行为交给手中所持的武器对象去完成换一把武器攻击行为就随之改变而冒险者本身的代码无需任何修改。维基百科定义关于委托维基百科给出了如下经典定义在面向对象编程中委托指的是在另一个原始对象发送方的上下文中求值某个对象接收方的成员属性或方法。委托可以显式完成——通过把发送对象传递给接收对象这在任何面向对象的语言中都可以做到也可以隐式完成——通过语言的成员查找规则这要求语言本身对该特性提供支持。本仓库中的示例采用的就是显式委托委托方在构造时将具体实现对象传入从而把工作转交出去。程序化示例Java 中的打印机委托1. 定义统一接口Printer委托模式的第一步是抽象出一个接口让委托方与被委托方实现同一套契约。仓库中该接口位于 Printer.javapublic interface Printer { void print(final String message); }2. 三个具体的被委托实现接口有三个具体实现CanonPrinter、EpsonPrinter和HpPrinter分别对应佳能、爱普生和惠普三种打印机。它们都实现Printer接口并真正完成打印动作这里以日志输出模拟打印Slf4j public class CanonPrinter implements Printer { Override public void print(String message) { LOGGER.info(Canon Printer : {}, message); } } Slf4j public class EpsonPrinter implements Printer { Override public void print(String message) { LOGGER.info(Epson Printer : {}, message); } } Slf4j public class HpPrinter implements Printer { Override public void print(String message) { LOGGER.info(HP Printer : {}, message); } }这三个类的仓库位置分别在 CanonPrinter.java、EpsonPrinter.java 和 HpPrinter.java。可以看到它们才是「真正干活」的 Delegate——消息被拼接上各自的品牌前缀后输出。3. 委托控制器PrinterController委托方Delegator是PrinterController位于 PrinterController.java。它同样实现Printer接口但不提供打印实现而是在构造时接收一个Printer实例并在print方法中把工作转交出去public class PrinterController implements Printer { private final Printer printer; public PrinterController(Printer printer) { this.printer printer; } Override public void print(String message) { printer.print(message); } }从源码注释可以看出设计者的两个意图当Printer的实际实现发生变化时委托层依然可以正常工作当存在多个实现类且共享同一套委托控制逻辑时委托的收益最为明显。4. 客户端使用运行时切换行为在客户端代码中仓库入口见 App.java根据传入控制器的具体打印机对象不同打印行为也随之不同——这正是「动态委托」的体现private static final String MESSAGE_TO_PRINT hello world; var hpPrinterController new PrinterController(new HpPrinter()); var canonPrinterController new PrinterController(new CanonPrinter()); var epsonPrinterController new PrinterController(new EpsonPrinter()); hpPrinterController.print(MESSAGE_TO_PRINT); canonPrinterController.print(MESSAGE_TO_PRINT); epsonPrinterController.print(MESSAGE_TO_PRINT);程序输出HP Printer : hello world Canon Printer : hello world Epson Printer : hello world调用方只与PrinterController交互完全不感知背后是哪个具体打印机类在执行实现了调用方与实现方的彻底解耦。类图与运行时协作委托模式的结构与交互流程可用仓库中的两张图清晰呈现。首先是类图从类图可以看到核心结构Printer接口定义print(String)契约PrinterController作为委托方持有Printer类型的依赖被委托对象三个打印机类实现同一接口并真正完成打印。其次是时序图展示请求如何在 Client → Delegator → Delegate 之间流转时序图完整展示了委托的核心调用链客户端向委托方发出请求 → 委托方把请求转发给被委托对象 → 被委托对象处理并返回 → 委托方再将结果回传给客户端。这与PrinterController.print()直接调用printer.print()的实现一一对应。源码级验证单元测试如何印证委托仓库中的测试类 DelegateTest.java 用三个用例分别验证了委托到不同打印机的行为Test void testCanonPrinter() { var printerController new PrinterController(new CanonPrinter()); printerController.print(MESSAGE); assertEquals(Canon Printer : Test Message Printed, appender.getLastMessage()); } Test void testHpPrinter() { var printerController new PrinterController(new HpPrinter()); printerController.print(MESSAGE); assertEquals(HP Printer : Test Message Printed, appender.getLastMessage()); } Test void testEpsonPrinter() { var printerController new PrinterController(new EpsonPrinter()); printerController.print(MESSAGE); assertEquals(Epson Printer : Test Message Printed, appender.getLastMessage()); }测试通过自定义的InMemoryAppender捕获 SLF4J 日志断言委托后输出的最终消息包含了对应打印机的品牌前缀从测试层面证实了「请求确实被转发到了被委托对象」这一核心语义。另有 AppTest.java 用于验证程序入口可正常启动运行。适用场景何时使用委托模式根据文档与仓库实现委托模式适用于以下情形降低方法与所属类的耦合让对象的行为实现可以被独立替换而不需要改动使用方代码需要一组行为一致、但未来可能变化的组件多个组件对外表现相同接口但具体实现可以随时在运行时切换希望用组合复用取代继承复用当不想或不适合通过继承来扩展行为时委托提供了一种「持有并转交」的替代方案需要在运行时使用多个可互换的 Helper 类如本例中在运行时自由选用 HP、Canon、Epson 三种打印实现。Java 生态中的真实应用委托模式在 Java 生态中被广泛使用文档与代码之外可以结合常见实践印证java.awt.event包监听器Listener机制常被用于委托处理事件Java 集合框架的包装类java.util.Collections许多包装器并不自己实现逻辑而是把操作委托给被包装的集合对象Spring Framework 的 IoC 容器Bean 之间大量通过委托协作一个 Bean 把任务委托给其他 Bean 执行。这些例子共同印证了委托模式「持有接口、转交实现」的核心思想在工业界的普遍价值。优点与权衡优点Benefits减少子类化对象可以把操作委托给不同对象并在运行时切换从而显著减少为每种行为创建子类的需求促进复用被委托对象的代码可以被多个委托方共享复用提升灵活性通过把任务委托给 Helper 对象类可以在运行时动态改变自身行为而无需修改其源码。权衡Trade-offs运行时开销委托引入了额外的间接层indirection可能带来轻微的性能成本复杂度上升由于需要额外管理和维护参与委托的类与接口整体设计会变得更复杂。与相关模式的关系Composite组合模式组合模式中常借助委托将组件特有的行为委托给子组件执行Strategy策略模式策略模式的典型结构就是一个上下文对象把任务委托给策略对象与委托模式高度契合Proxy代理模式代理本质上是委托的一种形式——代理对象通过控制对另一个对象的访问并将工作委托给该对象执行。这也解释了为什么委托模式常被称为 Proxy Pattern。总结委托模式提供了一条「不靠继承、靠组合」的行为复用与解耦路径通过统一接口 持有引用 运行时转交调用方只需面对稳定的外观而真实实现可以被灵活替换。本仓库的 Delegation 模式模块 用 7 个 Java 类1 个接口、1 个委托控制器、3 个打印机实现、1 个入口类加配套单元测试给出了一个可编译、可运行、可验证的最小完整示例是理解并落地委托模式的理想参考。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐Camunda服务任务Java委托与表达式执行Camunda服务任务Java委托与表达式执行 引言 在企业级业务流程管理BPM中服务任务Service Task是实现自动化业务逻辑的核心组件。C后端工作流自动化流程编排深入解析 Java 委托模式Delegation Pattern用对象组合实现高效任务分派深入解析 Java 委托模式Delegation Pattern用对象组合实现高效任务分派 委托模式Delegation Pattern是 java示例工程教程如何通过BigFive Personality Test快速了解自己的人格特质10个关键步骤如何通过BigFive Personality Test快速了解自己的人格特质10个关键步骤 想要深入了解自己的性格特征吗BigFive Personali上一篇Windows窗口置顶神器AlwaysOnTop让重要窗口始终在最前面工作效率提升300%下一篇HyperFrames v0.7.72 值得升级吗分布式渲染与确定性媒体处理 3 大变化讲透指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →