设计模式详解(十五)——模板方法模式

模板方法模式简介

模板方法模式定义

模板方法模式(Template Method Pattern)是行为型设计模式的一种,用于定义算法的框架结构,将算法的具体步骤延迟到子类中实现。模板方法使得子类可以不改变算法的结构即可重新定义该算法的某些特定步骤。模板方法模式是基于继承的代码复用技术。该模式通过定义一个抽象类,其中包含一个模板方法,该方法定义了算法的基本结构,并调用一系列抽象方法来完成算法中的特定步骤。子类继承抽象类并实现其中的抽象方法,从而定制化算法的具体步骤,但整体算法结构保持不变。模板方法模式提供了一种简单的扩展方式,使得算法的框架可以复用,同时允许子类灵活地实现特定步骤,符合开闭原则和单一职责原则。通过模板方法模式,我们能够将算法的不变部分和可变部分进行分离,使得算法更加灵活和可扩展。这种设计模式有助于减少代码重复,提高代码复用性,并使得系统更加易于维护和扩展。

模板方法模式包含以下角色:

  1. 抽象类(Abstract Class):定义了模板方法和抽象方法,其中模板方法定义算法的框架结构,包含一系列调用抽象方法的步骤,其中可能包含具体实现或调用抽象方法。它给出了一个顶级逻辑框架,而框架的某些步骤是延迟到子类中实现的。而抽象方法由子类实现,在抽象类中定义一些具体方法以及钩子方法(Hook Method),供子类调用。
  2. 具体子类(Concrete Subclass):实现抽象类所定义的一个或多个抽象方法,它们是一些可变的操作,子类通过扩展抽象类来重用不变部分的代码,但对于可变部分,子类可以重新实现以改变算法的行为。

模板方法模式优缺点:

优点:

  1. 代码复用性高:模板方法将算法的框架结构抽象到父类中,可以被多个子类共享和复用,避免了重复编写相似代码的问题。
  2. 灵活性:模板方法模式允许子类灵活地实现特定步骤,定制化算法的具体实现,同时保持整体算法结构不变,提高了系统的灵活性。
  3. 提高代码可读性:模板方法将算法的框架结构清晰地展现在抽象类中,使得代码逻辑更加清晰,易于理解和维护。
  4. 扩展性好:当需要增加新的算法步骤时,只需在抽象类中增加新的抽象方法,并让子类去实现,而不需要修改现有的子类代码。
  5. 控制子类行为:通过模板方法,父类可以控制子类的行为,确保它们按照预定的流程执行。

缺点:

  1. 限制子类的灵活性:由于模板方法定义了算法的框架结构,子类必须按照父类定义的步骤来实现具体方法,可能会限制子类的灵活性。
  2. 增加新的抽象方法可能导致子类变化:如果在抽象类中增加新的抽象方法,那么所有的子类都必须实现这个方法,否则编译会出错。这可能会增加子类的实现成本。
  3. 增加了类的个数:由于每个子类都需要实现抽象类中的抽象方法,因此随着算法步骤的增加或变化,子类的数量可能会增多,导致系统结构变得复杂。

使用场景

  1. 算法框架固定:当有多个类共享相似的算法框架结构,但各自的具体实现细节不同时,可以使用模板方法模式将算法的框架结构抽象到父类中,实现代码复用。
  2. 代码复用:当需要在不同类中实现相似的算法,但又不希望重复编写相同的代码时,可以使用模板方法模式将公共部分抽象到父类中,提高代码复用性。
  3. 固定流程:当算法包含固定的执行步骤或流程,但各个步骤的具体实现可能不同,可以使用模板方法模式定义算法的基本结构,让子类实现具体步骤。
  4. 扩展框架的功能:当需要扩展一个框架的功能,而又不希望修改原有框架的代码时,模板方法模式是一个很好的选择。通过定义抽象方法和模板方法,可以在不改变框架整体结构的情况下,增加新的功能或修改现有功能的具体实现。
  5. 控制子类行为:通过模板方法模式,可以在父类中控制子类的行为,确保子类按照规定的流程执行,同时允许子类灵活地定制特定步骤。

以下举一个模板方法模式的例子:

下面通过一个简单的例子来演示。

比如生活中,假如我们去运动的步骤基本固定的,分为先去运动场,选一种运动类型(比如:篮球,足球,羽毛球等),然后换上对应运动的鞋(比如:篮球鞋,足球鞋,羽毛球鞋等),然后去运动,再回家。现通过模板方法模式来用代码模拟这个过程,用户是可以选择什么运动类型,穿什么鞋子

创建抽象类(Abstract Class)

java 复制代码
/**
 * 抽象类(Abstract Class)
 */
public abstract class SportsProcess {
    //模板方法
    public final void process() {
        this.goStadium(); // 去运动场
        this.sportType(); // 运动类型
        this.sportShoe(); // 运动鞋
        this.sporting(); // 运动
        this.goHome(); // 回家
    }

    public void goStadium() {
        System.out.println("去运动场");
    }

    public abstract void sportType(); // 运动类型

    public abstract void sportShoe(); // 运动鞋

    public void sporting() {
        System.out.println("运动中");
    }

    public void goHome() {
        System.out.println("回家");
    }

}

创建具体子类(Concrete Subclass)

java 复制代码
/**
 * 具体子类:足球
 */
public class Football extends SportsProcess {
    @Override
    public void sportType() {
        System.out.println("选择足球");
    }

    @Override
    public void sportShoe() {
        System.out.println("穿足球鞋");
    }
}
java 复制代码
/**
 * 具体子类:篮球
 */
public class Basketball extends SportsProcess {
    @Override
    public void sportType() {
        System.out.println("选择篮球");
    }

    @Override
    public void sportShoe() {
        System.out.println("穿篮球鞋");
    }
}

创建客户端(Client)

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 选足球
        Football football = new Football();
        football.process();
        System.out.println("===================");

        // 选篮球
        Basketball basketball = new Basketball();
        basketball.process();
    }
}

输出结果如下所示:

java 复制代码
去运动场
选择足球
穿足球鞋
运动中
回家
===================
去运动场
选择篮球
穿篮球鞋
运动中
回家

在上述例子中,我们定义了一个抽象类为SportsProcess,里面定义了模板方法和抽象方法,模板方法里包含了一系列调用抽象方法的步骤。而抽象方法由子类实现,在抽象类中也定义一些钩子方法(Hook Method)为sportType和sportShoe,供子类调用。而两个具体的运动子类(具体子类),实现抽象类所定义两个抽象方法,分别是sportType和sportShoe。如果用户想要添加其它运动,只要添加具体子类就行了,无需改动抽象类。

总而言之:

模板方法模式是一种行为设计模式,用于定义算法的框架结构,将算法的通用部分抽象到父类中,同时允许子类实现特定步骤,以定制化算法的具体实现。该模式包含抽象类、具体类,通过这些角色的协作,实现了算法的框架结构和具体步骤的分离,提高了代码复用性、灵活性和可扩展性。

模板方法模式的优点包括代码复用、灵活性、符合开闭原则和提高代码可读性;然而,也存在限制子类灵活性和增加类个数的缺点。适用于算法框架固定、代码复用、固定流程、框架设计和控制子类行为等场景。

总之,模板方法模式是一种非常实用的设计模式,能够帮助我们更好地组织和管理具有相似逻辑结构的代码,提高系统的灵活性和可扩展性。

以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git

相关推荐
小小小妮子~13 分钟前
框架专题:设计模式
设计模式·框架
先睡14 分钟前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
wm104330 分钟前
java web springboot
java·spring boot·后端
smile-yan31 分钟前
Provides transitive vulnerable dependency maven 提示依赖存在漏洞问题的解决方法
java·maven
老马啸西风32 分钟前
NLP 中文拼写检测纠正论文-01-介绍了SIGHAN 2015 包括任务描述,数据准备, 绩效指标和评估结果
java
Earnest~36 分钟前
Maven极简安装&配置-241223
java·maven
皮蛋很白38 分钟前
Maven 环境变量 MAVEN_HOME 和 M2_HOME 区别以及 IDEA 修改 Maven repository 路径全局
java·maven·intellij-idea
青年有志40 分钟前
JavaWeb(一) | 基本概念(web服务器、Tomcat、HTTP、Maven)、Servlet 简介
java·web
上海研博数据44 分钟前
flink+kafka实现流数据处理学习
java
KpLn_HJL1 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode