这篇系列文章将按照以下结构逐一介绍不同种类的设计模式:

1. 创建型模式

2. 结构型模式

3. 行为型模式

通过这一系列文章,深入了解这些不同类型的设计模式,以及它们如何在软件开发中发挥关键作用。


前言

在软件开发中,设计模式是一种被广泛接受的可复用解决方案,用于解决在软件设计中常见的问题。设计模式为开发人员提供了一种通用的指导,帮助他们设计和实施高质量、易维护、可扩展的软件系统。

本文将快速入门行为型模设计模式中的模板方法模式。
模板方法模式思维导图

一、模板方法模式简介

1.1 什么是模板方法模式?

模板方法模式是一种行为型设计模式,它定义了一个算法的骨架,将算法的一些步骤延迟到子类中实现。这种模式使得子类可以在不改变算法结构的情况下重新定义算法的某些步骤。

1.2 为什么需要模板方法模式(优点)

模板方法模式有以下优点:

  • 封装不变部分:模板方法将算法的不变部分封装在父类中,子类只需要实现变化的部分,提高代码的复用性。
  • 提供扩展点:模板方法允许子类重写父类的某些步骤,以实现自己的特定需求。
  • 提高可维护性:通过将算法的结构固定在父类中,减少了代码的重复,提高了代码的可维护性。

1.3 模板方法模式的不足

模板方法模式可能存在以下不足:

  • 限制了灵活性:由于算法的结构在父类中固定,可能限制了子类的灵活性。
  • 增加了类的个数:每个具体子类都需要实现一些特定的步骤,可能会导致类的个数增加。

1.4 模板方法模式的结构

模板方法模式由以下角色组成:

  • 抽象类(AbstractClass):定义了模板方法,其中包含了算法的骨架,通常包括若干抽象方法和具体方法。
  • 具体子类(ConcreteClass):实现抽象类中的抽象方法,以完成具体的算法步骤。

1.5 模板方法模式的应用场景

模板方法模式适用于以下情况:

  • 在多个子类中有一些共同的行为,但各子类的具体实现略有不同。
  • 需要封装算法的骨架,使得子类可以在不改变算法结构的情况下重新定义某些步骤。
  • 需要在父类中控制算法的执行顺序。

模板方法模式通常适用于以下应用场景:

  1. 框架设计: 框架开发中经常使用模板方法模式。框架定义了通用的算法结构,而具体的实现留给了开发者。例如,Java中的Servlet生命周期就是一个经典的框架应用,Servlet容器提供了Servlet的生命周期管理,而具体的Servlet开发者只需要实现doGet和doPost等方法。

  2. 库函数或工具类: 在开发库函数或工具类时,可以使用模板方法来定义一些通用操作,然后由开发者根据自己的需求来定制具体的操作。例如,Java的Collections.sort()方法使用了模板方法,允许开发者提供自定义的比较器。

  3. 流程控制: 当需要控制特定流程的顺序,但每个步骤可能有不同的具体实现时,模板方法非常有用。例如,订单处理系统可能有不同类型的订单,但订单的处理流程(接收订单、验证、处理支付、发货等)是相同的,只是每个步骤的具体实现可能不同。

  4. 游戏开发: 在游戏开发中,很多游戏关卡或角色拥有相似的行为和属性。模板方法可以用于定义游戏角色的行为骨架,而具体的游戏角色可以根据需要实现具体的行为。

  5. 数据库访问: 数据库操作的流程通常包括连接数据库、执行SQL查询、处理结果集等通用步骤。不同的数据库访问类可以使用模板方法,将通用的数据库操作步骤放在父类中,而具体数据库访问类实现具体的SQL查询和结果处理。

  6. 生命周期管理: 对象的生命周期管理涉及创建、初始化、销毁等过程,这些过程通常有固定的执行顺序。模板方法可以用于定义对象生命周期的通用结构,而具体子类可以实现对象的初始化和销毁过程。

二、模板方法模式的示例

我们使用模板方法模拟制作奶茶的过程。

首先,定义一个抽象类来表示奶茶的制作过程:

public abstract class TeaTemplate {
    // 模板方法,定义了奶茶制作的骨架
    public final void makeMilkTea() {
        boilWater();
        brewTea();
        addMilk();
        addToppings();
        serveTea();
    }

    // 基本方法,烧水
    public void boilWater() {
        System.out.println("烧水");
    }

    // 基本方法,冲泡茶
    public abstract void brewTea();

    // 基本方法,加牛奶
    public abstract void addMilk();

    // 基本方法,加入奶茶配料
    public abstract void addToppings();

    // 基本方法,将奶茶倒入杯子
    public void serveTea() {
        System.out.println("倒入杯子");
    }
}

然后,创建具体的奶茶类,继承自抽象类,并实现抽象方法:

public class MilkTea extends TeaTemplate {
    @Override
    public void brewTea() {
        System.out.println("冲泡红茶茶叶");
    }

    @Override
    public void addMilk() {
        System.out.println("加入鲜奶");
    }

    @Override
    public void addToppings() {
        System.out.println("加入珍珠和奶盖");
    }
}

public class GreenTea extends TeaTemplate {
    @Override
    public void brewTea() {
        System.out.println("冲泡绿茶");
    }

    @Override
    public void addMilk() {
        // 不提供具体的实现
    }

    @Override
    public void addToppings() {
        System.out.println("加入柠檬和蜂蜜");
    }
}

现在,你可以在奶茶店中使用这些具体的奶茶类来制作不同种类的奶茶,而不必重复制作奶茶的骨架代码。例如:

public class PearlTeaShop {
    public static void main(String[] args) {
        TeaTemplate milkTea = new MilkTea();
        TeaTemplate greenTea = new GreenTea();

        System.out.println("制作奶茶:");
        milkTea.makeMilkTea();

        System.out.println("制作绿茶:");
        greenTea.makeMilkTea();
    }
}

这里,MilkTea 和 GreenTea 类继承自 TeaTemplate,并实现了其中的抽象方法,以定义不同种类奶茶的制作过程。在奶茶店中,你可以轻松地制作不同种类的奶茶,而无需重复编写通用制作奶茶的代码。这就是模板方法模式的用途。

运行结果:

制作奶茶:
烧水
冲泡红茶茶叶
加入鲜奶
加入珍珠和奶盖
倒入杯子
制作绿茶:
烧水
冲泡绿茶
加入柠檬和蜂蜜
倒入杯子

总结

模板方法模式允许我们定义通用的算法骨架,提高了代码复用性,同时保留了灵活性,因为具体的步骤可以在子类中定制。这种模式有助于减少重复的代码,提高可维护性,并促使良好的设计实践。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐