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;
/**
* 模板方法测试
*
* @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)模板方法定一个抽象的类,由父类统一定义实现算法的步骤,具体实现延迟到子类,
* 属于算法"定制",对特定的重复的算法部分实现了封装,只对扩展的部分暴露给子类!
*
* 优点:
* 想必不用说,我们都可以看出来,模板方法的一个最大的好处就是实现了重复代码的复用!
* 另外一个就是,扩展很方便!
* 缺点:
* 和策略模式一样,也存在子类过多的情况出现,类一多,维护起来的复杂度就增加了!
*
* 假如,一个抽象类有4个子类,你可能会说,也就才4个啊,半个小时都能看的透透彻彻了
* 假如,一个抽象类有100个子类,你可能会皱着眉头说,卧槽,这特么还是人吗,怎么写了这么多?
* 所以,类并不是越多越能体现系统的健壮性,反而多了会适得其反噢!
*/
}
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 商品查询业务类
*
* @Author zhaoshuangjian 2023-03-25 下午21:44
*/
public class GoodsQueryServiceImpl {
public Object query(String sql) throws SQLException{
return new JdbcTemplate().executeQuery(new GoodsQueryStatementCallBack(sql));
}
}
/**
* 内部类 == 用户查询数据库操作对象回调类
*/
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;
}
}
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 数据库操作模板类
*
* @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();
}
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 数据库操作回调接口
*
* @Author zhaoshuangjian 2023-03-25 下午21:44
*/
public interface StatementCallback {
Object doInStatement(Statement stmt) throws SQLException;
}
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板And回调实现;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 用户查询业务类
*
* @Author zhaoshuangjian 2023-03-25 下午21:44
*/
public class UserQueryServiceImpl{
public Object query(String sql) throws SQLException{
return new JdbcTemplate().executeQuery(new UserQueryStatementCallBack(sql));
}
}
/**
* 内部类 == 用户查询数据库操作对象回调类
*/
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;
}
}
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 模拟JDB模板类(可以理解为伪代码说明)
*
* @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;
}
/**
* 基于结果集进行定制,由具体的子类实现
* @param rs 结果集
* @return 数据模型对象
*/
protected abstract Object doInStatement(ResultSet rs) throws SQLException;
}
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 商品数据库操作(模板)实现类
*
* @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;
}
}
package com.zhaoshuangjian.mode14_模板模式.mode14.JDBC模板方法实现;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 用户数据库操作(模板)实现类
*
* @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;
}
}
package com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤;
/**
* 定义抽象算法类
*
* @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]);
}
/**
* 根据字符分割公式,提取double数组
* @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;
}
/**
* 公开(钩子)方法,子类和父类进行信息交互,子类可以使用默认的父类方法,也可以重写改方法
*/
public void hookSay(){
System.out.println("父类说:算法步骤的顺序我已经定好了,尔等子类照着做就行!");
}
/**
* 根据a和b的值计算结果,这个必须由子类来实现,父类帮不了了
* @param numA 第一个数字
* @param numB 第二个数字
* @return 两个数字计算的结果
*/
protected abstract double calculate(double numA ,double numB);
}
package com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤;
/**
* 加法运算
*
* @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说:接下来,由我来计算结果!");
}
}
package com.zhaoshuangjian.mode14_模板模式.mode14.父类固定算法步骤;
/**
* 减法运算
*
* @Author zhaoshuangjian 2023-03-25 下午21:44
*/
public class Sub extends AbstractCalculator{
@Override
protected double calculate(double numA, double numB) {
return numA - numB ;
}
}