zoukankan      html  css  js  c++  java
  • 模板模式讲解一

    一、模板

    模板,很经典、也很常用的一种模式。无处不在,如,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;
    }
    View Code

    ②、采用匿名类的方式

    根据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;
        }
    View Code

    根据名字查询

    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;
        }
    View Code

    ③、模板(类似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;
        }
    View Code
  • 相关阅读:
    第二周例行报告
    洛谷 P3384 【模板】轻重链剖分
    洛谷 P3380 【模板】二逼平衡树(树套树)
    洛谷 P4568 [JLOI2011]飞行路线
    2018 ICPC Asia Nanjing Regional Preliminary L. Magical Girl Haze
    牛客 2020 牛客国庆集训派对 day8 G. Shuffle Cards
    洛谷 P3224 [HNOI2012]永无乡
    洛谷 P1486 [NOI2004]郁闷的出纳员
    洛谷 P3391 【模板】文艺平衡树
    洛谷 P3369 【模板】普通平衡树
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/5492779.html
Copyright © 2011-2022 走看看