模板模式讲解

一、模板

模板,很经典、也很常用的一种模式。无处不在,如,spring jdbcTemplate。模板,个人理解, 讲大同小异的东西抽出它们的共性,提供标准的套路。

二、为什么要用模板?

假设场景,我们需要查询个人资料信息,现提供两个api,getPersonById(int id)、 getPersonListByName(String name)

1、我们先来看下不使用模板的情况

①、注册jdbc、建立连接

 1 static final String DB_URL = "jdbc:mysql://localhost/testdb";
 2     static final String USER = "root";
 3     static final String PWD = "root";
 4
 5     private static Connection connection = null;
 6
 7     static {
 8         try {
 9             // 注册JDBC驱动程序:以打开与数据库的通信信道
10             Class.forName("com.mysql.jdbc.Driver");
11             // 获取连接
12             connection = DriverManager.getConnection(DB_URL, USER, PWD);
13         } catch (ClassNotFoundException e) {
14             throw new RuntimeException("ClassNotFoundException");
15         } catch (SQLException e) {
16             throw new RuntimeException("SQLException");
17         }
18     }

②、根据Id查询

 1 public static List<Person> getPersonById(int id) {
 2         List<Person> res = new ArrayList<Person>();
 3         PreparedStatement ps = null;
 4         ResultSet rs = null;
 5         try {
 6             String sql = "select * from person where id = ?";
 7             ps = (PreparedStatement) connection.prepareStatement(sql);
 8             ps.setInt(1, id);
 9             rs = ps.executeQuery();
10             while (rs.next()) {
11                 res.add(new Person(rs.getInt("id"), rs.getString("name")));
12             }
13             return res;
14         } catch (SQLException e) {
15
16         } finally {
17             if (connection != null) {
18                 try {
19                     connection.close();
20                 } catch (SQLException e) {
21
22                 }
23             }
24             if (ps != null) {
25                 try {
26                     ps.close();
27                 } catch (SQLException e) {
28
29                 }
30             }
31             if (rs != null) {
32                 try {
33                     rs.close();
34                 } catch (SQLException e) {
35
36                 }
37             }
38         }
39         return null;
40     }

③、根据名字查询

 1 public static List<Person> getPersonListByName(String name) {
 2         List<Person> res = new ArrayList<Person>();
 3         PreparedStatement ps = null;
 4         ResultSet rs = null;
 5         try {
 6             String sql = "select * from person where name = ?";
 7             ps = (PreparedStatement) connection.prepareStatement(sql);
 8             ps.setString(1, name);
 9             rs = ps.executeQuery();
10             while (rs.next()) {
11                 res.add(new Person(rs.getInt("id"), rs.getString("name")));
12             }
13             return res;
14         } catch (SQLException e) {
15
16         } finally {
17             if (connection != null) {
18                 try {
19                     connection.close();
20                 } catch (SQLException e) {
21
22                 }
23             }
24             if (ps != null) {
25                 try {
26                     ps.close();
27                 } catch (SQLException e) {
28
29                 }
30             }
31             if (rs != null) {
32                 try {
33                     rs.close();
34                 } catch (SQLException e) {
35
36                 }
37             }
38         }
39         return null;
40     }

从②、③我们可以看出来,都一段冗余的判断关闭连接等代码,而且这些非业务性代码不应该浸入系统。代码看起来也不是很清晰。那有没有办法改进呢?答案当然是有的,模板可以很好解决这种诟病。

2、使用模板+回调结果(业务按照自身的需求封装,灵活性高)的场景

①、定义一个回调接口

public interface AssemblyResService<T> {

    public T assemblyRes(ResultSet rs) throws SQLException;
}

②、采用匿名类的方式

根据id查询

public static List<Person> getPersonById(int id) {
        List<Person> res = new ArrayList<Person>();
        try {
            String sql = "select * from person where id = ?";
            res = queryTemp(sql, new Object[]{id}, new AssemblyResService<Person>() {

                @Override
                public Person assemblyRes(ResultSet rs) throws SQLException {
                    return new Person(rs.getInt("id"), rs.getString("name"));
                }
            });
            return res;
        } catch (Exception e) {

        }
        return null;
    }

根据名字查询

public static List<Person> getPersonListByName(String name) {
        List<Person> res = new ArrayList<Person>();
        try {
            String sql = "select * from person where name = ?";
            res = queryTemp(sql, new Object[]{name}, new AssemblyResService<Person>() {

                @Override
                public Person assemblyRes(ResultSet rs) throws SQLException {
                    return new Person(rs.getInt("id"), rs.getString("name"));
                }
            });
            return res;
        } catch (Exception e) {

        }
        return null;
    }

③、模板(类似spring jdbcTemplate)

public static List<Person> queryTemp(String sql, Object[] params, AssemblyResService<Person> resService) {
        List<Person> res = new ArrayList<Person>();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = (PreparedStatement) connection.prepareStatement(sql);
            for(int i=0; i<params.length; i++) {
                ps.setObject(i+1, params[i]);
            }
            rs = ps.executeQuery();
            while (rs.next()) {
                res.add(resService.assemblyRes(rs));
            }
            return res;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {

                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {

                }
            }
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {

                }
            }
        }
        return null;
    }

时间: 2024-10-20 16:20:36

模板模式讲解的相关文章

模板模式讲解二

一.何为模板 在阎宏博士的<JAVA与模式>一书中开头是这样描述模板方法(Template Method)模式的: 模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现.这就是模板方法模式的用意. 二.模式结构设计 父类定义成一个抽象类,有一个具体实现方法,在这个具体实现方法会去调用此抽象类定义的抽象方法,这些抽象方法由子类继承实现,因为

模板模式

模板模式:解决某类事情的步骤有些是固定的,有些是会发生变化的,那么这时候我们可以为这类事情提供一个模板代码,从而提高效率. 模板模式的步骤: 1.先写出解决该类事件中的一件的解决方案. 2.分析代码,把会发生变化的代码抽取出来独立成一个方法.把该方法描述成一个抽象的方法. 3.是用final关键字修饰模板方法,防止别人重写你的模板方法. 例子:需求:编写一个计算程序运行时间的模板. 代码示例: 1 abstract class ProgramRuntime 2 { 3 public final

设计模式之 - 模板模式(Template Pattern)

引入:这几天在看一本讲spring源码的书<SPRING技术内幕>里面在讲加载配置文件的时候,可以有不同的加载方式,如根据文件系统目录加载配置文件(FileSystemXmlApplicationContext),类路径加载配置文件(ClassPathXmlApplicationContext),以及根据项目上下文目录(XmlWebApplicationContext)加载配置文件.这个在加载的过程中就使用了模板设计模式,所以就来学习下模板设计模式. 1. 模板设计模式在书中定义:  定义一个

设计模式整理_模板模式

模板模式在父类中定义了一个方法的模板,而子类可以动态的实现模板成分方法,但是模板中的方法顺序无法改变. 父类中的模板方法往往申明为final,用来保证方法不被子类覆盖,因为作为模板,是不可以改变的,但是模板方法内的一系列方法,可以由子类自己静态实现,同时在父类的模板方法中,可以定义钩子(hook)方法.方便子类对于模板方法的优化.下面用两个例子说明. /*没有钩子(hook)的模板方法,此时模板方法无法修改*/ public abstract class Model { public final

行为模式之Template(模板模式)

模板模式定义一系列的操作流程,并将其中的一个或多个操作的实现延迟到子类之中. 我们以牛奶加工过程为例,当然对其做了简化,具体流程如下图: 首先,将加工过程定义成一个抽象类: AbstractMilkProcess package com.design; /**牛奶加工过程 * @author wobendiankun *2015-1-21 下午08:01:57 */ public abstract class AbstractMilkProcess { /** *挤奶 */ protected

设计模式——模板模式(C++实现)

模板模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 模板模式通过把不变的行为搬移到超类,去除子类中的重复代码来体现它的优势. 通过继承和多态来实现. 行为型模式. spp业务框架中的server_task(CServerTask类)就是这么一个东西.非常常用的一个模式. 使用场景: 1.有多个子类共有的方法,且逻辑相同. 2.重要的.复杂的方法,可以考虑作为模板方法. 1 #include <iostream>

设计模式(7)--模板模式

//7.模板模式 //ver1 //考试试卷类 class TestPaper { public: void TestQuestion1(){} void TestQuestion2(){} virtual string Answer1() { return ""; } virtual string Answer2() { return ""; } }; class TestPaperA : public TestPaper { public: void TestQ

咸蛋系列一●《模板模式构建随机对象生成》2 构思

随机对象生成可以说是随机数生成的一个延伸,在实际使用中,我们可能要生成的不是一个简简单单的数字,而是像数字.大小写字符.中文汉字.算数表达式等. 由于其实现相对简单,取各种随机对象的源码网上也比比皆是,因而貌似也没人做一个通用的.可扩展的随机对象生成. 博主要不是因为闲得蛋疼也是不会想到做这个东西的,好了,言归正传.分析随机对象生成,其要点无外乎三点: 1. 设置随机对象集: 2. 获取一个或多个随机对象: 3. 获取一个或多个不重复随机对象: 在这三点中,后两者算法皆固定,仅设置对象集不同,故

引入模板模式重构FtpClientUtil

在<ftp上传与下载>文章中,封装一个Ftp上传下载的工具类,主要代码如下: 上传: /**上传文件 * @param remoteFileName 远程文件名称 * @param locaFileName 本地文件名称 */ public void upload(String remoteFileName,String locaFileName){ FTPClient ftp=null; try { ftp = new FTPClient(); ftp.addProtocolCommandL