Java 23 种设计模式:从踩坑到精通 | 番外:模板方法模式 —— 智能家居回家模式实战

发布时间:2026/8/18 6:33:58
Java 23 种设计模式:从踩坑到精通 | 番外:模板方法模式 —— 智能家居回家模式实战 Java 23 种设计模式从踩坑到精通 | 番外模板方法模式 —— 智能家居回家模式实战摘要模板方法模式定义一个操作中的算法骨架将某些步骤延迟到子类中实现使得子类可以在不改变算法整体结构的情况下重新定义某些特定步骤。它通过“好莱坞原则”让父类控制流程子类只负责填空。本文结合智能家居“回家模式”的场景完整展示如何用模板方法固定“开灯→开空调→播放音乐”的标准流程并通过钩子方法实现灵活控制同时与策略模式深度对比帮你掌握“固定骨架、填充细节”的设计精髓。️本文阅读地图3 分钟速览为什么回家模式和离家模式的代码重复度这么高模板方法三件套模板方法、抽象方法、钩子方法手写回家模式固定流程 可选步骤的经典实现模板方法 vs 策略继承 vs 组合的终极抉择面试必问“模板方法为什么要加final钩子方法有什么作用”《Java 23 种设计模式从踩坑到精通》开篇系列介绍与目录 正篇Template Method 模板方法模式—— 定义算法骨架交给子类填充细节 当前番外 · 模板方法模式 × 智能家居回家模式 返回系列总目录1. 智能家居模式流程的痛点在智能家居系统中有多种场景模式回家模式、离家模式、睡眠模式等。每种模式都有固定的执行步骤但部分步骤的实现细节不同。以“回家模式”为例标准流程是开灯 → 开空调 → 播放音乐。如果为每种模式都写一套代码classHomeMode{voidexecute(){turnOnLight();// 开灯turnOnAC();// 开空调playMusic();// 播放音乐}}classAwayMode{voidexecute(){turnOffLight();// 关灯turnOffAC();// 关空调// 不播放音乐}}这种方式导致大量重复的流程骨架代码而且如果某天需要统一调整流程顺序比如先开空调再开灯所有模式类都要修改。更麻烦的是某些步骤如是否播放音乐需要根据用户偏好动态决定静态代码无法优雅实现。模板方法模式的解决思路将流程骨架开灯→开空调→播放音乐定义在抽象父类中并声明为final防止子类篡改。其中“开灯”、“开空调”作为抽象方法由子类实现具体细节“播放音乐”作为钩子方法由子类可选覆盖。父类控制整个流程子类只负责填空。1.1 你的场景该不该用模板方法判断标准是 → 用模板方法否 → 用其他方式多个类有完全相同的流程仅部分步骤不同✅❌需要控制流程的执行顺序防止子类篡改✅❌需要在父类中提供“钩子”让子类可选干预流程✅❌需要动态替换整个算法而非仅修改部分步骤❌考虑策略模式2. 模板方法模式 UML智能家居回家模式场景3. 完整源码实现3.1 抽象模板类 (AbstractClass)/** * 抽象模板类定义回家模式的算法骨架 */publicabstractclassAbstractClass{/** * 模板方法定义算法骨架声明为 final 防止子类篡改流程 */publicfinalvoidtemplateMethod(){System.out.println( 正在执行回家模式...);primitiveOperation1();// 步骤1开灯primitiveOperation2();// 步骤2开空调if(hook()){// 步骤3钩子方法控制是否执行playMusic();// 步骤4播放音乐可选}System.out.println(✅ 回家模式执行完毕\n);}/** * 抽象方法1开灯子类必须实现 */protectedabstractvoidprimitiveOperation1();/** * 抽象方法2开空调子类必须实现 */protectedabstractvoidprimitiveOperation2();/** * 钩子方法默认返回 true子类可覆盖以控制流程 */protectedbooleanhook(){returntrue;}/** * 具体方法播放音乐公共逻辑通常不开放给子类修改 */privatevoidplayMusic(){System.out.println( 正在播放Welcome Home...);}}白话templateMethod()是流程控制器final保证没人能改顺序。primitiveOperation1/2是“填空题”子类必须实现。hook()是“开关”——默认返回true子类可以覆盖它来跳过音乐播放。3.2 具体子类 (ConcreteClass)/** * 具体子类主人回家模式 */publicclassConcreteClassextendsAbstractClass{OverrideprotectedvoidprimitiveOperation1(){System.out.println( 客厅主灯已开启亮度80%);}OverrideprotectedvoidprimitiveOperation2(){System.out.println( ❄️ 空调已开启制冷24℃);}// 默认继承 hook() 返回 true会播放音乐// 如果需要静音模式可以覆盖// Override// protected boolean hook() {// return false;// }}白话这个子类只实现了开灯和开空调没有覆盖钩子方法所以回家时会播放音乐。如果用户想静音回家只需再写一个子类覆盖hook()返回false。3.3 客户端测试publicclassClient{publicstaticvoidmain(String[]args){// 多态调用客户端只关心模板方法不关心具体实现AbstractClasshomeModenewConcreteClass();homeMode.templateMethod();}}4. 运行结果 正在执行回家模式... 客厅主灯已开启亮度80% ❄️ 空调已开启制冷24℃ 正在播放Welcome Home... ✅ 回家模式执行完毕5. 核心角色回顾角色职责对应代码AbstractClass定义模板方法和抽象/钩子方法AbstractClassConcreteClass实现抽象方法可选覆盖钩子ConcreteClass6. 模板方法三件套元素关键字是否必须说明模板方法public final必须算法骨架子类不可重写抽象方法protected abstract必须除非有默认强制子类实现的步骤钩子方法protected可选提供默认逻辑子类按需覆盖好莱坞原则“Don’t call us, we’ll call you.”——父类在需要的时候回调子类的方法子类永远不会主动调用父类的模板方法。7. 模板方法模式 vs 策略模式对比项模板方法模式策略模式复用方式继承子类重写父类方法组合接口实现控制权父类控制流程子类只填空客户端选择策略策略控制算法粒度控制算法的骨架封装整个算法典型应用HttpServlet、JdbcTemplateComparator、支付方式一句话记忆模板方法是“继承填空”——骨架固定细节可填策略是“组合替换”——整个算法可换。8. 模板方法模式的优缺点优点缺点公共逻辑集中到抽象类避免代码重复继承限制子类必须继承抽象类Java 单继承流程控制父类控制整体流程保证一致性钩子过多会让父类难以理解易扩展新增子类只需实现可变部分子类受限必须遵循父类定义的骨架9. 六大设计原则体现原则体现单一职责抽象父类管理骨架子类负责具体步骤开闭原则新增不同模式只需新增子类无需修改父类里氏替换所有子类都可替换抽象父类依赖倒置父类依赖抽象方法子类实现具体逻辑接口隔离抽象类只定义必要的抽象方法和钩子迪米特法则客户端只与抽象父类交互不关心子类细节附 模板方法模式 UML源码智能家居回家模式场景startuml title Java 23 种设计模式从踩坑到精通 footer 折哥 | 智能物流与Java实战 1. 全局样式配置 skinparam backgroundColor #FEFEFE skinparam shadowing false skinparam classBorderColor #333333 skinparam classFontColor #1A1A1A skinparam classFontSize 14 skinparam noteFontSize 12 skinparam noteFontColor #555555 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 skinparam abstract { BackgroundColor #FFF3E0 BorderColor #E65100 FontColor #BF360C } 2. 抽象模板类 abstract class AbstractClass { # {abstract} primitiveOperation1() : void # {abstract} primitiveOperation2() : void # hook() : boolean {final} templateMethod() : void } note right of AbstractClass b抽象模板类/b -- • btemplateMethod/b: 模板方法定义算法骨架 • bprimitiveOperation/b: 抽象方法子类必须实现 • bhook/b: 钩子方法子类可选择性覆盖 end note 3. 具体实现类 class ConcreteClass extends AbstractClass { primitiveOperation1() : void primitiveOperation2() : void # hook() : boolean } note right of ConcreteClass b具体子类/b -- 实现父类定义的抽象步骤 可选择性覆盖钩子方法 end note enduml 《Java 23 种设计模式从踩坑到精通》快速导航开篇系列介绍与目录正篇Template Method 模版方法模式—— 定义算法骨架交给子类填充细节当前番外 · 模板方法模式 × 智能家居回家模式你在这里创建型模式汇总结构型模式汇总行为型模式汇总 关注《Java 23 种设计模式从踩坑到精通》用 25 篇文章彻底吃透设计模式。福利预告全系列代码及 UML 源码将在完结时统一打包开放点击「关注」「收藏」第一时间获取。 除了设计模式我也在深挖智能物流实战WMS、托盘调度、机器学习落地。欢迎点击头像看看专栏 《出版社物流WMS智能调度实战》、《电商多平台电子面单对接实战》。技术相通思路可鉴。