Java 设计模式・模板方法模式篇:从思想到代码实现

张开发
2026/5/8 16:29:05 15 分钟阅读

分享文章

Java 设计模式・模板方法模式篇:从思想到代码实现
一、行为型模式在面向对象的世界里如何优雅地组织对象间的交互、分配职责是每一位开发者都会反复思考的问题。直接硬编码交互逻辑固然简单但当业务复杂度上升、对象协作关系变得错综复杂时这种方式就会让代码变得僵化、难以扩展。行为型设计模式正是为了解决这一痛点而诞生的一套思想体系。它们关注如何定义对象之间的通信方式和职责分配通过命令、迭代、观察者、策略等手段让对象间的协作更具灵活性、可复用性和可维护性。在 Java 开发中行为型模式主要包含以下 11 种经典实现模板方法模式 (Template Method)定义一个操作中的算法的骨架而将一些步骤延迟到子类中使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。策略模式 (Strategy)定义一系列的算法把它们一个个封装起来并且使它们可相互替换让算法独立于使用它的客户而变化。Java 设计模式・策略模式篇从思想到代码实现-CSDN博客命令模式 (Command)将一个请求封装为一个对象从而使你可以用不同的请求对客户进行参数化支持可撤销操作。Java 设计模式・命令模式篇-CSDN博客责任链模式 (Chain of Responsibility)将请求的发送者和接收者解耦使多个对象都有机会处理这个请求形成一条处理链。Java 设计模式・责任链模式篇从思想到代码实现-CSDN博客状态模式 (State)允许一个对象在其内部状态改变时改变它的行为对象看起来似乎修改了它的类。Java 设计模式・状态模式篇从思想到代码实现-CSDN博客观察者模式 (Observer)定义对象间的一种一对多的依赖关系当一个对象的状态发生改变时所有依赖它的对象都得到通知并被自动更新。Java 设计模式・观察者模式篇从思想到代码实现-CSDN博客中介者模式 (Mediator)用一个中介对象来封装一系列的对象交互使各对象不需要显式地相互引用从而降低耦合。迭代器模式 (Iterator)提供一种方法顺序访问一个聚合对象中的各个元素而又不暴露其内部的表示。访问者模式 (Visitor)表示一个作用于某对象结构中的各元素的操作它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。备忘录模式 (Memento)在不破坏封装性的前提下捕获一个对象的内部状态并在该对象之外保存这个状态以便以后恢复。解释器模式 (Interpreter)给定一个语言定义它的文法的一种表示并定义一个解释器这个解释器使用该表示来解释语言中的句子。二、模板方法模式2.1 介绍定义一个操作中的算法的骨架而将一些步骤延迟到子类中。使得子类可以不改变一个算法的整体结构即可重定义该算法的某些特定步骤。2.2 角色抽象类Abstract Class负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。模板方法定义了算法的骨架按某种顺序调用其包含的基本方法。为防止恶意操作一般模板方法都加上 final 关键词基本方法是实现算法各个步骤的方法是模板方法的组成部分。基本方法又可以分为三种抽象方法(Abstract Method) 一个抽象方法由抽象类声明、由其具体子类实现。具体方法(Concrete Method) 一个具体方法由一个抽象类或具体类声明并实现其子类可以进行覆盖也可以直接继承。钩子方法(Hook Method) 在抽象类中已经实现包括用于判断的逻辑方法和需要子类重写的空方法两种。一般钩子方法是用于判断的逻辑方法这类方法名一般为isXxx返回值类型为boolean类型。具体子类Concrete Class实现抽象类中所定义的抽象方法和钩子方法它们是一个顶级逻辑的组成步骤。三、代码实现为了方便理解本文采用中文定义类名3.1 抽象类public abstract class 吃饭模板 { /** * 模板方法 */ public final void eat(){ //第一步点餐 order(); //第二步备注 remark(); //第三步吃东西 eatFood(); //第四步结账 pay(); } /** * 具体方法 */ private void order() { System.out.println(开始点餐……); } /** * 钩子方法 */ protected void remark(){} /** * 抽象方法 */ protected abstract void eatFood(); /** * 具体方法 */ private void pay(){ System.out.println(结账……); } }3.2 具体子类public class 具体吃饭 extends 吃饭模板{ Override protected void eatFood() { System.out.println(吃面……); } Override protected void remark(){ System.out.println(备注吃面要加辣); } }四、优缺点4.1 优点代码复用将相同的算法骨架和固定步骤放在抽象父类中避免在多个子类中重复编写相同代码。流程标准化通过final修饰的模板方法确保算法的整体结构不被破坏保证了流程的一致性和稳定性。易于扩展新增业务场景时只需新增子类并实现抽象的可变步骤无需修改原有代码符合开闭原则。职责清晰将不变的行为移到父类可变的行为留给子类实现分离了职责便于维护。4.2 缺点类数量膨胀每增加一个新的业务变体就需要新增一个子类当可变步骤过多时会导致类的数量急剧增加。继承限制模板方法模式依赖于继承机制而 Java 是单继承的这在一定程度上限制了类的设计灵活性。反向控制子类的执行结果会影响父类的行为“好莱坞原则”Dont call us, well call you这可能会让代码逻辑变得不那么直观增加理解难度。维护成本当抽象类中的模板方法需要调整时所有继承它的子类都会受到影响维护成本较高。五、适用场景有固定流程的业务场景框架与类库设计需要控制算法步骤顺序的场景六、对比学习6.1 对比工厂方法模式Java 设计模式・工厂模式篇从思想到代码实现-CSDN博客两者都属于 “好莱坞原则”别找我们我们找你的典型应用且都基于继承但关注点不同。维度模板方法模式工厂方法模式 (Factory Method)核心关注点定义执行流程怎么做。定义对象创建做什么。在父类中的角色父类调用子类的方法来完成某一步骤。父类调用子类的方法来创建对象。关系工厂方法模式本质上是模板方法模式的一种特殊应用模板方法用于创建对象。案例JdbcTemplate(执行查询流程)Collection.iterator()(父类定义规范子类创建具体迭代器)6.2 对比建造者模式Java 设计模式・建造者模式篇从思想到代码实现-CSDN博客两者都涉及 “步骤”但目的完全不同。维度模板方法模式建造者模式 (Builder)目的完成一个复杂的过程 / 算法。构建一个复杂的产品对象。步骤性质步骤是算法的执行顺序通常有依赖关系。步骤是组装部件通常可以调整顺序。执行者由父类模板方法自动调度。由导演类Director或客户端手动调用。七、源码举例7.1 InputStreampublic abstract class InputStream implements Closeable { ... public abstract int read() throws IOException; public int read(byte b[]) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); if (len 0) { return 0; } int c read(); if (c -1) { return -1; } b[off] (byte)c; int i 1; try { for (; i len ; i) { c read(); if (c -1) { break; } b[off i] (byte)c; } } catch (IOException ee) { } return i; } ... }无参的read()方法是抽象方法要求子类必须实现, 而read(byte b[], int off, int len)方法 调用了无参的抽象的read()方法。7.2 SpringAbstractApplicationContextSpring 容器初始化Spring 容器的初始化流程完全基于模板方法核心逻辑AbstractApplicationContext的refresh()方法是模板方法定义了容器初始化的完整流程将beanFactory初始化、Bean 实例化等部分步骤延迟到子类。关键代码片段public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { // 模板方法容器初始化的完整骨架 public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准备刷新固定步骤 prepareRefresh(); // 2. 获取 BeanFactory抽象步骤由子类实现 ConfigurableListableBeanFactory beanFactory obtainFreshBeanFactory(); // 3. 准备 BeanFactory固定步骤 prepareBeanFactory(beanFactory); try { // 4. 后置处理 BeanFactory可选步骤子类可重写 postProcessBeanFactory(beanFactory); // 5. 执行 BeanFactoryPostProcessor固定步骤 invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册 BeanPostProcessor固定步骤 registerBeanPostProcessors(beanFactory); // 7. 初始化 MessageSource固定步骤 initMessageSource(); // ... 省略其他固定步骤 // 8. 刷新完成固定步骤 finishRefresh(); } catch (BeansException ex) { // 异常处理固定步骤 destroyBeans(); cancelRefresh(ex); throw ex; } } } // 抽象步骤由子类如 ClassPathXmlApplicationContext实现 protected abstract ConfigurableListableBeanFactory obtainFreshBeanFactory(); }八、其他相关设计模式Java 设计模式・总结目录篇从思想到代码实现-CSDN博客

更多文章