1.模板方法测试
package com.zhaoshuangjian.mode14_模板模式; import com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现.GoodsQueryServiceImpl; import com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现.UserQueryServiceImpl; import com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现.AbstractJdbcTemplate; import com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现.GoodsTemplateImpl; import com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现.UserTemplateImpl; import com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤.AbstractCalculator; import com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤.Plus; import com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤.Sub; import java.sql.SQLException; /** * <p>模板方法测试</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class TemplateTest { public static void main(String[] args) throws SQLException{ calculate(); jdbc(); jdbcCallBack(); } private static void calculate(){ System.out.println("====================== 11 + 2 加法公式计算 "); AbstractCalculator plus = new Plus(); System.out.println(plus.calculate("11 + 2", "\\+")); System.out.println("====================== 11 - 2 减法公式计算"); AbstractCalculator sub = new Sub(); System.out.println(sub.calculate("11 - 2", "\\-")); } private static void jdbc() throws SQLException { System.out.println("====================== 用户数据层操作实现 "); AbstractJdbcTemplate userTemplate = new UserTemplateImpl(); userTemplate.execute("select * from user "); System.out.println("====================== 商品数据层操作实现 "); AbstractJdbcTemplate goodsTemplate = new GoodsTemplateImpl(); goodsTemplate.execute("select * from goods "); } private static void jdbcCallBack() throws SQLException { System.out.println("====================== 用户数据层操作实现(模板+回调) "); UserQueryServiceImpl queryService = new UserQueryServiceImpl(); queryService.query("select * from user "); System.out.println("====================== 商品数据层操作实现(模板+回调)"); GoodsQueryServiceImpl goodsQueryService = new GoodsQueryServiceImpl(); goodsQueryService.query("select * from goods "); } /** * * 百科中如此描述模板方法: * 模板方法模式定义了一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式。 * 让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤。 * * 模板方法和策略模式有点像,都是由子类最终实现算法,二者区别是: * (1)策略模式定义了一个统一的算法接口,由具体的算法子类实现,所有的算法方法必须暴露给子类, * 由子类来实现,这样会产生一个问题,就是在执行算法之前如果有大量的数据准备工作,则会 * 增加子算法方法块代码的臃肿度,使得大量代码重复得不到复用! * (2)模板方法定一个抽象的类,由父类统一定义实现算法的步骤,具体实现延迟到子类, * 属于算法"定制",对特定的重复的算法部分实现了封装,只对扩展的部分暴露给子类! * * 优点: * 想必不用说,我们都可以看出来,模板方法的一个最大的好处就是实现了重复代码的复用! * 另外一个就是,扩展很方便! * 缺点: * 和策略模式一样,也存在子类过多的情况出现,类一多,维护起来的复杂度就增加了! * * <p>假如,一个抽象类有4个子类,你可能会说,也就才4个啊,半个小时都能看的透透彻彻了</p> * <p>假如,一个抽象类有100个子类,你可能会皱着眉头说,卧槽,这特么还是人吗,怎么写了这么多?</p> * <p>所以,类并不是越多越能体现系统的健壮性,反而多了会适得其反噢!</p> */ }
2.商品查询业务类
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现; import java.sql.SQLException; import java.sql.Statement; /** * <p>商品查询业务类</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class GoodsQueryServiceImpl { public Object query(String sql) throws SQLException{ return new JdbcTemplate().executeQuery(new GoodsQueryStatementCallBack(sql)); } } /** * <p>内部类 == 用户查询数据库操作对象回调类</p> */ class GoodsQueryStatementCallBack implements StatementCallback { private String sql; public GoodsQueryStatementCallBack(String sql) { this.sql = sql; } @Override public Object doInStatement(Statement stmt) throws SQLException { System.out.println("执行SQL语句:" + sql); System.out.println("数据集处理成功,返回Goods数据实体对象"); return null; } }
3.数据库操作模板类
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; /** * <p>数据库操作模板类</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class JdbcTemplate { public final Object execute(StatementCallback callback) throws SQLException { // 1、首先获取数据库连接对象 Connection connection = getConnection(); // 2、根据连接获取statement对象(数据库操作对象) Statement stmt = getStament(connection); // 3、根据stmt回调子类方法 --> 执行sql语句获取最终结果 return callback.doInStatement(stmt); // 资源的释放这里我就省略了 } private Connection getConnection(){ System.out.println("获取数据库连接"); return null; } private Statement getStament(Connection connection){ System.out.println("获取数据库操作对象"); return null; } public Object executeQuery(StatementCallback callback) throws SQLException{ return execute(callback); } /** * 如果该类是抽象类,则定义以下四个抽象方法,则其子类必须全部实现 * 回调的好处,即子类只需要实现父类中的某一个方法即可,该方法可以抽离成一个接口的方法 */ // protected abstract void A(); // protected abstract void B(); // protected abstract void C(); // protected abstract void D(); }
4.数据库操作回调接口
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现; import java.sql.SQLException; import java.sql.Statement; /** * <p>数据库操作回调接口</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public interface StatementCallback { Object doInStatement(Statement stmt) throws SQLException; }
5.用户查询业务类
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现; import java.sql.SQLException; import java.sql.Statement; /** * <p>用户查询业务类</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class UserQueryServiceImpl{ public Object query(String sql) throws SQLException{ return new JdbcTemplate().executeQuery(new UserQueryStatementCallBack(sql)); } } /** * <p>内部类 == 用户查询数据库操作对象回调类</p> */ class UserQueryStatementCallBack implements StatementCallback{ private String sql ; public UserQueryStatementCallBack(String sql){ this.sql = sql; } @Override public Object doInStatement(Statement stmt) throws SQLException { System.out.println("执行SQL语句:"+sql); System.out.println("数据集处理成功,返回User数据实体对象"); return null; } }
6.模拟JDB模板类(可以理解为伪代码说明)
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * <p>模拟JDB模板类(可以理解为伪代码说明)</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public abstract class AbstractJdbcTemplate { public final Object execute(String sql) throws SQLException { // 1、首先获取数据库连接对象 Connection connection = getConnection(); // 2、根据连接获取statement对象(数据库操作对象) getStament(connection); // 3、使用数据库操作对象来执行对应的SQL语句 ResultSet rs = executeQuery(sql); // 4、最后基于查询的数据集,处理并返回最终结果 return doInStatement(rs); // 资源的释放这里我就省略了 } private Connection getConnection(){ System.out.println("获取数据库连接"); return null; } private Statement getStament(Connection connection){ System.out.println("获取数据库操作对象"); return null; } private ResultSet executeQuery(String sql){ System.out.println("执行SQL语句:"+sql); return null; } /** * <p>基于结果集进行定制,由具体的子类实现</p> * @param rs 结果集 * @return 数据模型对象 */ protected abstract Object doInStatement(ResultSet rs) throws SQLException; }
7.商品数据库操作(模板)实现类
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现; import java.sql.ResultSet; import java.sql.SQLException; /** * <p>商品数据库操作(模板)实现类</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class GoodsTemplateImpl extends AbstractJdbcTemplate { @Override protected Object doInStatement(ResultSet rs) throws SQLException { // 遍历数据集 // while (rs.next()){ // // dosomething // } System.out.println("数据集处理成功,返回Goods数据实体对象"); return null; } }
8.用户数据库操作(模板)实现类
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现; import java.sql.ResultSet; import java.sql.SQLException; /** * <p>用户数据库操作(模板)实现类</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class UserTemplateImpl extends AbstractJdbcTemplate { @Override protected Object doInStatement(ResultSet rs) throws SQLException { // 遍历数据集 // while (rs.next()){ // // dosomething // } System.out.println("数据集处理成功,返回User数据实体对象"); return null; } }
9.定义抽象算法类
package com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤; /** * <p>定义抽象算法类</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public abstract class AbstractCalculator { public final double calculate(String formula , String splitChar){ // 1、第一步,先根据计算公式和分隔符,拿到要计算的数值(假设这个是核心,不对外公布) double[] splitArry = split(formula, splitChar); // 2、第二步,各个算法类代表发个言吧(默认不发言的,一律按父类说的来) hookSay(); // 3、第三步,话说完了,各个算法(子)类开始干活吧(这时候别再指望父类帮你默认实现了,休想!) return calculate(splitArry[0], splitArry[1]); } /** * <p>根据字符分割公式,提取double数组</p> * @param formula 计算公式 * @param splitChar 分隔字符 * @return double数组 */ private double[] split(String formula , String splitChar){ String array[] = formula.trim().split(splitChar); double arrayDouble[] = new double[2]; arrayDouble[0] = Double.parseDouble(array[0]); arrayDouble[1] = Double.parseDouble(array[1]); return arrayDouble; } /** * <p>公开(钩子)方法,子类和父类进行信息交互,子类可以使用默认的父类方法,也可以重写改方法</p> */ public void hookSay(){ System.out.println("父类说:算法步骤的顺序我已经定好了,尔等子类照着做就行!"); } /** * <p>根据a和b的值计算结果,这个必须由子类来实现,父类帮不了了</p> * @param numA 第一个数字 * @param numB 第二个数字 * @return 两个数字计算的结果 */ protected abstract double calculate(double numA ,double numB); }
10.加法运算
package com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤; /** * <p>加法运算</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class Plus extends AbstractCalculator{ @Override protected double calculate(double numA, double numB) { return numA + numB ; } /** * 重写父类钩子方法 */ @Override public void hookSay() { System.out.println("子类Plus说:接下来,由我来计算结果!"); } }
11.减法运算
package com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤; /** * <p>减法运算</p> * * @Author zhaoshuangjian 2023-03-25 下午21:44 */ public class Sub extends AbstractCalculator{ @Override protected double calculate(double numA, double numB) { return numA - numB ; } }