常用设计模式——模板方法模式

什么是模板方法模式

模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

主要解决:一些方法通用,却要在每一个子类都重写这些方法。

大概实现:将需要实现的算法抽象成一组步骤,在抽象类中定义好相关步骤的执行流程,其他需要自定义的特定步骤放到子类实现。

模板方法模式中的方法

模板方法中的方法可以分为两大类:模板方法和基本方法。

模板方法

一个模板方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。

一个抽象类可以有任意多个模板方法,而不限于一个。每一个模板方法都可以调用任意多个具体方法。

基本方法

基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。

●  抽象方法:由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。

●  具体方法:由抽象类声明并实现,而子类并不实现或置换。

●  钩子方法:由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。简单点来说就是在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法就被称为"钩子"。

应用场景

我们在完成某个功能,这个功能需要执行一系列的步骤,而且这一系列步骤基本相同,只是某些步骤在具体实现上有所不同,这个时候我们就可以考虑使用模板方法模式。

在代码中如果有多个子类共有的方法,且逻辑相同的时候,我们就可以使用模板方法模模式。

优缺点

优点:

1、封装不变部分,扩展可变部分。

2、提取公共代码,便于维护。

3、行为由父类控制,子类实现。

缺点: 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

实例

下面我们以一个执行数据库语句为例,在数据库连接中,我们执行一条语句的流程一般是固定的几步:

1.获取连接 2.执行语句 3.关闭连接

抽象类:

java 复制代码
/**
 * 使用抽象类来定义模板方法和基本方法
 */
public abstract class DatabaseTemplate {

    //模板方法
    final <T> T executeSql(String sql){
        T result;
        getConnection();
        //判断是否是查询语句,非查询语句开启事务
        if (isSelect()){
            //执行语句
            result = execute(sql);
        }else {
            //开启事务
            openTransaction();
            //执行语句
            result = execute(sql);
        }
        closeConnection();
        return result;
    }

    //抽象方法,让子类实现
    abstract <T> T execute(String sql);

    //具体方法,获取连接
    void getConnection() {
        System.out.println("获取连接");
    }

    //具体方法,关闭连接
    void closeConnection(){
        System.out.println("关闭连接");
    }

    //具体方法,开启事务
    void openTransaction() {
        System.out.println("开启事务");
    }

    // 钩子方法,决定是否需要事务
    boolean isSelect() {
        return true;
    }

}

子类:

java 复制代码
/**
 * 查询语句
 */
public class QueryTemplate extends DatabaseTemplate{

    @Override
    String  execute(String sql) {
        System.out.println("查询成功");
        return "成功";
    }


}

/**
 * 更新语句
 */
public class UpdateTemplate extends DatabaseTemplate{

    @Override
    Integer execute(String sql) {
        System.out.println("更新成功");
        return 1;
    }


    /**
     * 重写钩子方法,添加事务
     * @return
     */
    @Override
    boolean isSelect() {
        return false;
    }

}

测试:

java 复制代码
public static void main(String[] args) {
        UpdateTemplate updateTemplate = new UpdateTemplate();
        updateTemplate.executeSql("update table  set column_name = b");
}

输出:

获取连接
开启事务
更新成功
关闭连接
相关推荐
子非鱼9212 分钟前
SpringBoot快速上手
java·spring boot·后端
techzhi6 分钟前
Apifox CLI + GitLab CI:接口自动化测试实施记录
java·ci/cd·kubernetes·gitlab·yapi·运维开发·fastapi
我爱娃哈哈15 分钟前
SpringBoot + XXL-JOB + Quartz:任务调度双引擎选型与高可用调度平台搭建
java·spring boot·后端
小宇的天下22 分钟前
Synopsys Technology File and Routing Rules Reference Manual (1)
java·服务器·前端
Coder_Boy_32 分钟前
基于SpringAI的在线考试系统-AI智能化拓展
java·大数据·人工智能·spring boot
n***333536 分钟前
TCP/IP协议栈深度解析技术文章大纲
java·spring boot
奋进的芋圆40 分钟前
Java 线程池深度指南(JDK 17+)
java
蓁蓁啊1 小时前
GCC 头文件搜索路径:-I vs -idirafter 深度解析
java·前端·javascript·嵌入式硬件·物联网
Coder_Boy_1 小时前
基于SpringAI的在线考试系统-核心业务流程图(续)
java·大数据·人工智能·spring boot·流程图
毕设源码-钟学长1 小时前
【开题答辩全过程】以 基于Springboot vue肢体残疾人就业服务网站的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端