前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java设计模式(四)模板方法模式

Java设计模式(四)模板方法模式

作者头像
每天学Java
发布2020-06-01 18:02:16
4070
发布2020-06-01 18:02:16
举报
文章被收录于专栏:每天学Java

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

在前面我们聊过适配器模式回调模式策略模式。其中适配器模式是结构型设计模式,它的设计是为了适应两个原本不兼容的接口而诞生的设计模式。回调模式不属于23种设计模式,它指得是通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。而策略模式属于行为型设计模式,它是用来识别对象之间的常用交流模式并加以实现(也就是使得接口独立于使用它的客户端而独自改变)。今天仍然学习一下属于行为型设计模式的,模版方法模式。

案例

模版方法模式定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可冲定义该算法的某些特定步骤。什么意思呢?将一些步骤延迟到子类中,可以理解为实现的细节放入到子类中,而整个实现过程在模版方法中早已定义好。

在最初学习数据的时候,你还记得有哪几步吗?

1. 加载驱动

2. 建立连接

3. 获取Statement

4. 拼接参数(针对PreparedStatement)

5. 执行

6. 返回结果

7. 销毁连接

写了一个连接代码:

代码语言:javascript
复制
// JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://IP:3306/DateBase?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai";
    // 数据库的用户名与密码,需要根据自己的设置
    static final String USER = "root";
    static final String PASS = "pwd";
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        try{
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);
            // 打开链接
            System.out.println("连接数据库...");
            conn = DriverManager.getConnection(DB_URL,USER,PASS);
            // 执行查询
            System.out.println(" 实例化Statement对象...");
            stmt = conn.createStatement();
            String sql;
            sql = "SELECT id, userName FROM userInfo";
            ResultSet rs = stmt.executeQuery(sql);
            // 展开结果集数据库
            while(rs.next()){
                // 通过字段检索
            }
            // 完成后关闭
            rs.close();
            stmt.close();
            conn.close();
        }catch(SQLException se){
            // 处理 JDBC 错误
            se.printStackTrace();
        }catch(Exception e){
            // 处理 Class.forName 错误
            e.printStackTrace();
        }finally{
            // 关闭资源
            try{
                if(stmt!=null) stmt.close();
            }catch(SQLException se2){
            }// 什么都不做
            try{
                if(conn!=null) conn.close();
            }catch(SQLException se){
                se.printStackTrace();
            }
        }
        System.out.println("Goodbye!");
    }

这是我们初学Java连接数据库时候,自己写数据库的连接和查询,可能后续我们也对上面代码进行了优化,比如我们将1,2,3,4,7这几个步骤单独拿出来进行封装,而把5,6步骤暴露出去。其实这就是模版方法模式。

这里大家看一下过程:

代码语言:javascript
复制
public class TemplateMethod {

    public TemplateMethod() {

    }

    private void conn() {
        System.out.println("连接");
    }

    public void exe(Object... param) {
        conn();
        try {
            //子类中需要的业务逻辑
            for (int i = 0; i < param.length; i++) {
                System.out.println(param[i]);
            }
        } finally {
            unconn();
        }
    }

    private void unconn() {
        System.out.println("释放");
    }

    public static void main(String[] args) {
        new TemplateMethod().exe(1,2,3,4,5);
    }
}

简单的说就是对不变的代码进行一次抽取,对代码的重复利用。不知道有没有小伙伴还记得定义:模版方法模式定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可冲定义该算法的某些特定步骤。

我们上面好像没有涉及到子类,只是简单的抽离代码。我们来看一下Spring中的JdbcTemplate这个类

代码语言:javascript
复制
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations

JdbcTemplate继承了JdbcAccessor,而JdbcAccessor就是一个抽象类,换句话说可以把它当作模版,它的方法比如getDataSource在JdbcTemplate被调用(大家可以去看一下源码)。

代码语言:javascript
复制
public abstract class JdbcAccessor implements InitializingBean {

我们继续往下看,这里我们自己定义一个抽象类出来

代码语言:javascript
复制
abstract class TemplateAccess {

    public Boolean isClose() {
    //默认关闭
        return true;
    }

    private void conn() {
        System.out.println("连接");
    }

    public abstract void exe();

    private void unconn() {
        if (isClose()) {
            System.out.println("子类说关闭连接");
        } else {
            System.out.println("子类说暂时不关闭");
        }

    }

    public void run() {
        conn();
        exe();
        unconn();
    }
}

这个抽象类中,一共有5个方法,其中exe()是抽象方法,isClose()我们通常叫它钩子函数,通过它我们能知道是否关闭数据库连接。而run方法是一次数据执行的完整过程,子类只需要重写exe()方法,如果对于是否关闭数据库有特殊要求,可以重写钩子函数。我们来写一个它的子类。

代码语言:javascript
复制
class Temp1 extends TemplateAccess {


    @Override
    public Boolean isClose() {
        return false;
    }

    @Override
    public void exe() {
        System.out.println("执行计划1");
    }

    public static void main(String[] args) {
        new Temp1().run();
    }
}

执行结果:

代码语言:javascript
复制
Connected to the target VM, address: '127.0.0.1:50843', transport: 'socket'
连接
执行计划1
子类说暂时不关闭
Disconnected from the target VM, address: '127.0.0.1:50843', transport: 'socket'

Process finished with exit code 0

看到这里对于模版方法模式是否已经理解了?

其实模版模式很简单,也许你平时就用的很多,只是你不知道它就是一种模式


今天小程序更细题库:进入小程序

1.什么是设计模式?你是否在你的代码里面使用过任何设计模式?

2.模板模式解决了什么问题?

3.策略模式有什么好处??

4.你可以说出几个在JDK库中使用的设计模式吗?

5.举出一个例子,在这种情况你会更倾向于使用抽象类,而不是接口

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档