模板模式初探

关于模板模式,大家可以参阅 模板方法模式深度解析(一)

原始的jdbc

关于原始的jdbc,如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;  

public class JDBC_Test2 {  

    public static void main(String[] args) {  

        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;
        String url="jdbc:mysql://localhost:3306/webexample?useUnicode=true&characterEncoding=UTF-8";
        String userName="root";
        String passWord="";
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn=DriverManager.getConnection(url,userName,passWord);
            st=conn.createStatement();
            rs=st.executeQuery("select * from admininfo");
            while (rs.next()) {
                System.out.println(rs.getString("Aname"));
            }  

        } catch (ClassNotFoundException e) {
            e.printStackTrace();           //log4j 具体记录
        }catch (SQLException e) {
            e.printStackTrace();
        }
        finally{
            try {
                if (rs!=null) {
                    rs.close();
                    rs=null;
                }
                if (st!=null) {
                    st.close();
                    st=null;
                }
                if (conn!=null) {
                    conn.close();
                    conn=null;
                }  

            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}  

我假定朋友们都有一定的编码经验,那么大家再看了最基本的jdbc后,心里应该会有两个想法

1 作为jdbc hello world级别的示例程序,上面的代码写的还是很不错的,该try catch的地方都注意到了

2 如果要大规模使用的话,就比较麻烦了,操作数据库的核心的代码很少,但是核心之前之后的操作却很多。









jdbc连接数据库 获取数据可以分为一下几步:

1 加载驱动 Class.forName("com.mysql.jdbc.driver");

2 获得连接  Connection con=DriverManager.getConnection(url,userName,password);

3 获得Statement  Statement st=con.createStatement();

4 执行sql并获得ResultSet rs=st.executeQuery(sql);

5 处理rs中的数据

             while (rs.next()) {  

                System.out.println(rs.getString("Aname"));  

            }  

6 处理异常

7 关闭连接









仔细看看,其实只有第五步是真正核心的,之前之后的都是那种万年不变的代码

使用模板模式

我们用模板模式来改装一下。

package templatemethod1;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public abstract class JDBCTemplate  {

	public Object execute(String sql) {
		String  url="";
		String  userName="";
		String  password="";
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		try{
			Class.forName("com.mysql.jdbc.driver");
			con=DriverManager.getConnection(url,userName,password);
			st=con.createStatement();
			rs=st.executeQuery(sql);
			//只把核心的第五步 抽象出来 交给子类处理
			Object object=doResultSet(rs);
			return object;                 

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

			}
		}
		return null;
	}
	//抽象出来 交给子类处理
	public abstract Object doResultSet(ResultSet rs);

}
package templatemethod1;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import model.Student;

public class JDBCTemplateStudentImpl extends JDBCTemplate {

        //doResultSet 就是关于获取Student的真正核心的代码
	@Override
	public Object doResultSet(ResultSet rs) {
		List<Student> userList = new ArrayList<Student>();  

        try {
        	Student student = null;
            while (rs.next()) {  

            	student = new Student();
            	student.setId(rs.getInt("id"));
            	student.setBirth(rs.getDate("birth"));
                userList.add(student);
            }
            return userList;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }  

}

最后的测试代码

package templatemethod1;

import java.util.List;
import model.Student;

public class TemplateMethodTest {

	public static void main(String[] args) {
		String  sql="select * from user";
		JDBCTemplate template=new JDBCTemplateStudentImpl();
		List<Student> students=(List<Student>) template.execute(sql);
	}

}

model.Student的代码我就不给出了,就是几个字段,getset方法而已。

回调

上面的模板方法OK不?

好着呢。

问题是,如果JDBCTemplate中有很多个抽象方法,那么我们就得重新很多方法。太累。









那我们能否只覆盖我们想要的呢?

这里就牵扯到一个名词,callback(回调)





所谓回调,就是方法参数中传递一个接口,父类在调用此方法时,必须调用方法中传递的接口的实现类。





我们直接看代码

package templatemethod2;

import java.sql.SQLException;
import java.sql.Statement;

public interface StatementCallback {
    //这个doInStatement相当于上面的doResultSet
    Object doInStatement(Statement stmt) throws SQLException;
}  
package templatemethod2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public  class JDBCTemplate  {

	public Object execute(StatementCallback action) {
		String  url="";
		String  userName="";
		String  password="";
		Connection con=null;
		Statement st=null;
		ResultSet rs=null;
		try{
			Class.forName("com.mysql.jdbc.driver");
			con=DriverManager.getConnection(url,userName,password);
			st=con.createStatement();
			Object object=action.doInStatement(st);
			return object;
		}
		//省略try catch

		return null;
	}

	public  Object query(StatementCallback action){
		return execute(action);
	}

}
下面的测试方法,只要给定一个sql,就能传回List<Student>
	@SuppressWarnings("unchecked")
	public List<Student> test2(final String sql) {

		JDBCTemplate jdbcTemplate = new JDBCTemplate();
		return (List<Student>) jdbcTemplate.execute(new StatementCallback() {
			@Override
			public Object doInStatement(Statement stmt) throws SQLException {
				ResultSet rs = stmt.executeQuery(sql);
				List<Student> userList = new ArrayList<Student>();

				Student user = null;
				while (rs.next()) {
					user = new Student();
					user.setId(rs.getInt("id"));
					user.setBirth(rs.getDate("birth"));
					userList.add(user);
				}
				return userList;
			}
		});

	}

参考资料

http://blog.csdn.net/lovelion/article/details/8299794

http://www.bubuko.com/infodetail-666886.html

从模板模式到JdbcTemplate的更多相关文章

  1. 模板模式(Template)

    行为型:Template(模板模式) 作为一个曾经爱好写文章,但是不太懂得写文章的人,我必须承认,开头是个比较难的起步. 模板模式常规定义:模板模式定义了一个算法步骤,把实现延迟到子类. 事实上模板模 ...

  2. java设计模式之模板模式以及钩子方法使用

    1.使用背景 模板方法模式是通过把不变行为搬到超类,去除子类里面的重复代码提现它的优势,它提供了一个很好的代码复用平台.当不可变和可变的方法在子类中混合在一起的时候, 不变的方法就会在子类中多次出现, ...

  3. Spring中常见的设计模式——模板模式

    一.模板模式的应用场景 模板模式又叫模板方法模式(Template Method Pattern),指定义一个算法的骨架,并允许自雷为一个或者多个步骤提供实现.模板模式使得子类可以在不改变算法结果的情 ...

  4. Spring中的设计模式:模板模式

    导读 模板模式在是Spring底层被广泛的应用,比如事务管理器的实现,JDBC模板的实现. 文章首发于作者的微信公众号[码猿技术专栏] 今天就来谈谈「什么是模板模式」.「模板模式的优缺点」.「模板模式 ...

  5. JAVA设计模式之模板模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述模板方法(Template Method)模式的: 模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式 ...

  6. Java设计模式之模板模式(Template )

    前言: 最近学习了Glide开源图片缓存框架,在学习到通过使用ModelLoader自定义数据源的时候,Glide巧妙的使用了Java的模板模式来对外暴露处理不同的Url数据源,今天来学习总结一下模板 ...

  7. Java设计模式(七) 模板模式

    [模板模式]在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 1,定义模板类 package com.pattern ...

  8. 模板模式与策略模式/template模式与strategy模式/行为型模式

    模板模式 模版模式,又被称为模版方法模式,它可以将工作流程进行封装,并且对外提供了个性化的控制,但主流程外界不能修改,也就是说,模版方法模式中,将工作的主体架构规定好,具体类可以根据自己的需要,各自去 ...

  9. 12. 星际争霸之php设计模式--模板模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

随机推荐

  1. Java第6次实验提纲(异常)

    PTA与参考资料 题集:集合 异常实验文件 第1次实验 1.1 7-1 常用异常 如何进行强制转换 如何捕获多种类型的异常 1.2 7-2 使用异常机制处理异常输入 在哪里加catch 1.3 7-3 ...

  2. 一例完全理解vue 2.0 的slots 和 functional render

    https://jsfiddle.net/pronan/mjqpmw0u/ 通过调节plan="bbb"的值, 比如换成plan="children",你会发现 ...

  3. mysql 数据类型别名参考

    To facilitate the use of code written for SQL implementations from other vendors, MySQL maps data ty ...

  4. Dynamics CRM Entity Relationship Many to Many (N:N)

    该博客对N:N的关系的查询列出了两种方式,一种RetrieveMultipleRequest,一种Fetch XML ,有谁对N:N关系的查询了解不是很深的可以学习下. http://andreasw ...

  5. Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)

    作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/52088039 最近在移植一个 JNI 项目, 比较纠结, A ...

  6. Android源码浅析(五)——关于定制系统,如何给你的Android应用系统签名

    Android源码浅析(五)--关于定制系统,如何给你的Android应用系统签名 今天来点简单的我相信很多定制系统的同学都会有一些特定功能的需求,比如 修改系统时间 静默安装 执行某shell命令 ...

  7. load balancer 配置参考

    https://wiki.ewu.edu/oit/Load_balancing_using_nginx

  8. Linux动态频率调节系统CPUFreq之三:governor

    在上一篇文章中,介绍了cpufreq的core层,core提供了cpufreq系统的初始化,公共数据结构的建立以及对cpufreq中其它子部件提供注册功能.core的最核心功能是对policy的管理, ...

  9. Dynamics CRM FORM脚本库加载本地脚本

    用传统的开发方式,js脚本都是保存在数据库中的,这样也方便迁移,但如果不想存数据库而是存在物理磁盘上,则可通过下述代码,将脚本存放在CRMWEB文件夹的某个路径下,每次都动态引用本地JS. funct ...

  10. Unsupported major.minor version 52.0

    今天运行项目,切换一下eclipse,运行程序突然发现普通的类main()方法无法运行,报错详细信息如下: Exception in thread "main" java.lang ...