ARTICLE DETAIL

资讯详情

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

Java 桥接模式(Bridge Pattern)源码级解析:基于 java-design-patterns 的武器与附魔组合示例

Java 桥接模式(Bridge Pattern)源码级解析:基于 java-design-patterns 的武器与附魔组合示例 示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载本篇技术指南以 java-design-patterns 仓库中 Bridge 模式模块bridge及其阿拉伯语文档localization/ar/bridge/README.md为核心结合仓库真实源码与测试系统讲解如何通过桥接模式分离抽象与实现使两者可独立变化。读完本文你将掌握 Bridge 模式的角色划分、组合优于继承的设计动机、完整 Java 实现与可验证的测试证据并能将其迁移到 GUI 框架、数据库驱动等真实场景。模式概述Handle/Body 与核心目标桥接模式Bridge Pattern还有一个广为人知的别名——Handle/Body句柄/主体。在 阿拉伯语文档 与 英文文档 中其意图被明确表述为将抽象abstraction与其实现implementation分离使得两者可以各自独立地变化。这一句定义是整个模式的核心。它意味着抽象层不再永久绑定某一个具体实现而是通过组合的方式持有一个实现接口的引用运行时可自由切换、替换甚至同时扩展多条类层次结构而互不影响。从 GOFGang of Four分类来看Bridge 属于结构型模式Structural Pattern在 README 元数据 中被标记为category: Structural、tag: Gang of Four。现实世界的类比武器与附魔的自由组合文档用一个非常直观的 RPG 场景解释该模式的动机想象你有一把武器它可以附加不同的附魔效果并且你希望允许任意武器 × 任意附魔的自由组合。你会怎么做是为每种武器 × 每种附魔的组合各创建一份副本还是创建独立的附魔对象按需装配到武器上桥接模式支持的是后者。如果用继承来实现当有 2 种武器剑、锤和 2 种附魔飞行、噬魂时就需要 2 × 2 4 个具体类当武器和附魔各扩展到 N 种类数量将爆炸为 N × M。而桥接模式把两个维度拆成两条独立的类层次用组合持有引用代替继承生成子类类数量降为 N M。用文档的简单说来总结Bridge 模式本质上是在偏好组合优于继承composition over inheritance。实现细节被从一条类层次中抽离出来推入另一条独立的类层次对象中。这一设计理念在 App.java 的类注释中同样被强调Composition over inheritance. The Bridge pattern can also be thought of as two layers of abstraction.组合优于继承。桥接模式也可视为两层抽象。参与角色与 UML 类图在仓库中桥接模式的四条经典角色一一对应经典角色本示例类职责Abstraction抽象Weapon接口定义高层操作wield()、swing()、unwield()Refined Abstraction细化抽象Sword、Hammer实现抽象接口持有Enchantment引用Implementor实现Enchantment接口定义低层操作onActivate()、apply()、onDeactivate()Concrete Implementor具体实现FlyingEnchantment、SoulEatingEnchantment实现附魔的具体行为下面这张来自仓库的 UML 类图完整呈现了上述静态结构bridge/etc/bridge.urm.png可以看到Sword与Hammer共同实现Weapon接口同时各自关联一个Enchantment类型的字段而Enchantment之下又有SoulEatingEnchantment、FlyingEnchantment两个具体实现——这正是两条独立类层次通过组合桥接的标准结构。仓库源码实现解读从接口到调用链抽象层Weapon 接口Weapon.java 是抽象层的契约定义了武器的基础动作并向外暴露其装配的附魔public interface Weapon { void wield(); void swing(); void unwield(); Enchantment getEnchantment(); }注意getEnchantment()的返回值类型是Enchantment接口而不是任何具体类这正是解耦的关键武器只认识附魔这个概念不关心它到底是飞行还是噬魂。细化抽象Sword 与 HammerSword.java 与 Hammer.java 结构完全对称都通过构造器注入一个final的Enchantment字段使用 Lombok 的AllArgsConstructor自动生成全参构造器并在每个动作方法内部把行为委托给附魔Slf4j AllArgsConstructor public class Sword implements Weapon { private final Enchantment enchantment; Override public void wield() { LOGGER.info(The sword is wielded.); enchantment.onActivate(); } Override public void swing() { LOGGER.info(The sword is swung.); enchantment.apply(); } Override public void unwield() { LOGGER.info(The sword is unwielded.); enchantment.onDeactivate(); } Override public Enchantment getEnchantment() { return enchantment; } }这段代码清晰展示了委托链武器的wield()/swing()/unwield()只负责自己的日志输出真正的特效逻辑全部转发给被注入的Enchantment。武器不用管附魔怎么实现附魔也不用管自己被装在哪把武器上。实现层Enchantment 接口Enchantment.java 定义了实现层的三个钩子方法public interface Enchantment { void onActivate(); void apply(); void onDeactivate(); }具体实现FlyingEnchantment 与 SoulEatingEnchantmentFlyingEnchantment.java 实现飞行附魔Slf4j public class FlyingEnchantment implements Enchantment { Override public void onActivate() { LOGGER.info(The item begins to glow faintly.); } Override public void apply() { LOGGER.info(The item flies and strikes the enemies finally returning to owners hand.); } Override public void onDeactivate() { LOGGER.info(The items glow fades.); } }SoulEatingEnchantment.java 实现噬魂附魔Slf4j public class SoulEatingEnchantment implements Enchantment { Override public void onActivate() { LOGGER.info(The item spreads bloodlust.); } Override public void apply() { LOGGER.info(The item eats the soul of enemies.); } Override public void onDeactivate() { LOGGER.info(Bloodlust slowly disappears.); } }两条层次就此成型武器侧是Weapon → Sword / Hammer附魔侧是Enchantment → FlyingEnchantment / SoulEatingEnchantment。未来新增武器如Axe或新增附魔如FireEnchantment只需各自扩展无需改动对方任何代码。入口调用链App.mainApp.java 是程序入口演示了任意组合的威力——骑士拿到噬魂剑女武神拿到飞行锤public static void main(String[] args) { LOGGER.info(The knight receives an enchanted sword.); var enchantedSword new Sword(new SoulEatingEnchantment()); enchantedSword.wield(); enchantedSword.swing(); enchantedSword.unwield(); LOGGER.info(The valkyrie receives an enchanted hammer.); var hammer new Hammer(new FlyingEnchantment()); hammer.wield(); hammer.swing(); hammer.unwield(); }注意组合的自由度同一把Sword也可以换装FlyingEnchantment同一个Hammer也可以装配SoulEatingEnchantment——2 种武器 × 2 种附魔的 4 种组合全部由构造器注入动态决定无需生成任何额外的组合类。运行时行为控制台输出与时序图运行App.main后控制台输出与文档记录完全一致The knight receives an enchanted sword. The sword is wielded. The item spreads bloodlust. The sword is swung. The item eats the soul of enemies. The sword is unwielded. Bloodlust slowly disappears. The valkyrie receives an enchanted hammer. The hammer is wielded. The item begins to glow faintly. The hammer is swung. The item flies and strikes the enemies finally returning to owners hand. The hammer is unwielded. The items glow fades.这段输出直观揭示了委托顺序每次武器动作后紧跟对应附魔特效证明武器层与附魔层在运行时以组合方式协作。下面这张来自仓库的时序图bridge/etc/bridge-sequence-diagram.png刻画了桥接模式通用的动态交互流程时序图的通用流程是客户端调用抽象层Abstraction的operation()→ 抽象层不亲自实现业务而是向实现层Implementor发起implementation()调用 → 实现层处理完返回 → 抽象层再把结果返回给客户端。映射到本示例就是App客户端调用Sword.wield()抽象层操作Sword内部转调enchantment.onActivate()实现层操作。测试验证源码级证据仓库为桥接模块提供了完整的单元测试可以从测试代码反向印证模式的调用关系WeaponTest.java 是武器测试的抽象基类使用 Mockito 对附魔进行打桩依次调用swing()、wield()、unwield()随后分别verify(enchantment).apply()、verify(enchantment).onActivate()、verify(enchantment).onDeactivate()并用verifyNoMoreInteractions确认附魔只被期望的方法触发——这从测试角度证明武器的每个动作都恰好委托给附魔的对应钩子方法。SwordTest.java 与 HammerTest.java 各自用mock(FlyingEnchantment.class)构造武器并复用基类测试方法验证两种武器在委托链上的行为一致性。AppTest.java 使用assertDoesNotThrow(() - App.main(new String[] {}))验证整个入口执行不抛异常。测试依赖JUnit Jupiter、Mockito在 bridge/pom.xml 中声明为test作用域运行环境通过 SLF4J Logback 提供日志输出maven-assembly-plugin将com.iluwatar.bridge.App配置为主类。项目结构与运行方式Bridge 模式模块位于仓库根目录下的 bridge 目录其结构为bridge/src/main/java/com/iluwatar/bridge/7 个生产类App、Weapon、Sword、Hammer、Enchantment、FlyingEnchantment、SoulEatingEnchantmentbridge/src/test/java/com/iluwatar/bridge/4 个测试类bridge/etc/UML 类图、时序图及其 PlantUML 源文件bridge/pom.xml模块构建配置父工程为仓库根 pom.xml版本 1.26.0-SNAPSHOT。本模块是标准 Maven 工程可独立查看与运行使用仓库根目录的 Maven Wrappermvnw执行测试或通过模块内配置的App主类运行示例。由于仓库为只读示例工程推荐以阅读源码、运行测试、对照 UML 图的方式学习。何时使用桥接模式适用场景阿拉伯语文档原样列出了以下适用条件这也是判断是否引入 Bridge 的标准需要避免抽象与实现的永久绑定例如实现必须在运行时被选择或切换的场景抽象与实现都应能通过继承独立扩展此时 Bridge 允许你组合不同的抽象与实现并各自独立演进实现的变更不应影响客户端即修改实现时客户端代码无需重新编译类层次出现类爆炸式增殖文档引用 Rumbaugh 的术语嵌套泛化nested generalizations来描述这类需要把对象拆成两部分的膨胀层次希望在多个对象间共享同一实现可能借助引用计数并对外隐藏这一事实如 Coplien 的String类中多个对象共享同一字符串表示。真实世界中的应用英文版 READMEbridge/README.md补充了三个经典的现实应用场景可作为迁移参考GUI 框架抽象是窗口Window实现是底层操作系统各自的窗口系统数据库驱动抽象是通用的数据库访问接口实现是各数据库厂商的专用驱动设备驱动抽象是设备无关的代码实现是设备相关的代码。这三类场景的共同点都是接口契约稳定、底层实现千差万别且频繁迭代与武器/附魔示例的解耦逻辑完全同构。优点与权衡优点接口与实现解耦高层操作与低层操作分离模块化程度更高可扩展性更强抽象层次与实现层次可各自独立扩展新增一方无需改动另一方隐藏实现细节客户端只面对抽象接口完全看不到底层实现。权衡复杂度上升对不熟悉该模式的开发者额外引入的抽象层会加大系统结构与代码的理解成本轻微运行时开销多一层抽象转发会带来少量性能损耗但在实践中通常可以忽略。与其他设计模式的关系在 bridge/README.md 中Bridge 与仓库内其他模式的差异被明确梳理Abstract Factory见 abstract-factory可与 Bridge 搭配使用用于创建与具体类无关的平台对象Adapter见 adapterAdapter 是为对象提供不同的接口而 Bridge 是把对象的接口与实现分离两者意图不同Composite见 compositeBridge 常与 Composite 配合用于建模组件的实现细节Strategy见 strategy两者都基于组合但意图不同——Strategy 用组合改变类的行为Bridge 用组合分离抽象与实现。参考资料与延伸阅读本模式的理论背景来自经典的面向对象设计文献GOF 的《Design Patterns: Elements of Reusable Object-Oriented Software》与《Head First Design Patterns》。想要进一步获取模式讲解与更多细节可继续阅读仓库内的英文原版文档 bridge/README.md其内容与本篇基于的 阿拉伯语文档 互为印证并包含序列图、真实应用与相关模式等更多素材。简而言之当你的系统出现一个抽象维度 × 多个实现维度的交叉组合且希望运行时自由切换、两边独立演进时桥接模式就是用组合替代继承、把类爆炸化解为两条优雅类层次的答案。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐Java 桥接模式Bridge Pattern实战指南在 java-design-patterns 中解耦抽象与实现Java 桥接模式Bridge Pattern实战指南在 java design patterns 中解耦抽象与实现 桥接模式Bridge是 GoF示例工程教程Corsair Exa 插件实战指南为你的 Agent 集成神经搜索、问答与 Webset 监控Corsair Exa 插件实战指南为你的 Agent 集成神经搜索、问答与 Webset 监控 导读 corsair dev/exa 是 Corsair示例工程教程claw-code 可靠 Worker 启动与会话控制G003 boot/session/preflight 验证地图全解claw code 可靠 Worker 启动与会话控制G003 boot/session/preflight 验证地图全解 导读 本文基于 claw code示例工程教程上一篇如何用DLSS Swapper解锁游戏隐藏性能3个实战技巧让帧率飙升45%下一篇Switch游戏安装终极指南Awoo Installer让你的游戏安装直接能用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表