男女做那个什么的视频网站,wordpress免费交易主题,蚌埠做网站公司,设计购物网站咋做1. 什么是模板方法模式
模板方法模式#xff08;Template Method Pattern#xff09;是一种行为设计模式#xff0c;它在操作中定义算法的框架#xff0c;将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。
模板方法模式的定义Template Method Pattern是一种行为设计模式它在操作中定义算法的框架将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。
模板方法模式的定义 在操作中定义算法的框架并将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法的某些步骤。 模板方法中的算法可以理解为广义上的业务逻辑并不是特指某一个实际的算法。定义中所说的算法的框架就是模板包含算法框架的方法就是模板方法。
模板方法模式包含以下主要角色
抽象父类定义一个算法所包含的所有步骤并提供一些通用的方法逻辑。具体子类继承自抽象父类根据需要重写父类提供的算法步骤中的某些步骤。
抽象类Abstract Class负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。 模板方法定义了算法的骨架按某种顺序调用其包含的基本方法。 基本方法是实现算法各个步骤的方法是模板方法的组成部分。基本方法又可以分为三种 抽象方法Abstract Method一个抽象方法由抽象类声明、由其具体子类实现。具体方法Concrete Method一个具体方法由一个抽象类或具体类声明并实现其子类可以进行覆盖也可以直接继承。钩子方法Hook Method在抽象类中已经实现包括用于判断的逻辑方法和需要子类重写的空方法两种。一般钩子方法是用于判断的逻辑方法这类方法名一般为isXxx返回值类型为boolean类型。 钩子在模板方法的父类中我们可以定义一个方法它默认不做任何事子类可以视情况要不要覆盖它该方法称为“钩子”。钩子方法一般是空的或者有默认实现。钩子的存在可以让子类有能力对算法的不同点进行挂钩。而要不要挂钩又由子类去决定。 2. 代码示例
/*** 抽象父类*/
public abstract class AbstractClassTemplate {void step1(String key) {System.out.println(在模板类中 - 执行步骤1);if (step2(key)) {step3();} else {step4();}step5();}boolean step2(String key) {System.out.println(在模板类中 - 执行步骤2);return x.equals(key);}abstract void step3();abstract void step4();void step5() {System.out.println(在模板类中 - 执行步骤5);}void run(String key) {step1(key);}
}public class ConcreteClassA extends AbstractClassTemplate {Overridevoid step3() {System.out.println(在子类A中 - 执行步骤 3);}Overridevoid step4() {System.out.println(在子类A中 - 执行步骤 4);}
}public class ConcreteClassB extends AbstractClassTemplate {Overridevoid step3() {System.out.println(在子类B中 - 执行步骤 3);}Overridevoid step4() {System.out.println(在子类B中 - 执行步骤 4);}
}public class Test01 {public static void main(String[] args) {AbstractClassTemplate concreteClassA new ConcreteClassA();concreteClassA.run();System.out.println();AbstractClassTemplate concreteClassB new ConcreteClassB();concreteClassB.run(x);}
}// 输出结果
在模板类中 - 执行步骤1
在模板类中 - 执行步骤2
在子类A中 - 执行步骤 4
在模板类中 - 执行步骤5在模板类中 - 执行步骤1
在模板类中 - 执行步骤2
在子类B中 - 执行步骤 3
在模板类中 - 执行步骤53. JdbcTemplate应用模板方法模式
在原生JDBC操作中需要执行以下步骤
获取connection获取statement获取resultset遍历resultset并封装成集合依次关闭connection, statement, resultset并考虑各种异常
上面步骤中大多数都是重复的、可复用的只有在遍历ResultSet并封装成集合的步骤是可定制的。每张表都映射不同的Java bean这部分代码是没有办法复用的只能定制。
// 模板方法用来执行 JDBC 操作返回结果集或受影响的行数
protected T T execute(ConnectionCallbackT action, boolean enforceReadOnly) throws DataAccessException {Assert.notNull(action, Callback object must not be null);Connection con DataSourceUtils.getConnection(obtainDataSource());try {boolean readOnly enforceReadOnly || isReadOnly();// 设置是否为只读连接prepareConnection(con, readOnly);// 执行具体的 JDBC 操作该方法为子类实现T result action.doInConnection(con);// 提交事务DataSourceUtils.commitIfNecessary(con, getDataSource());// 返回结果集或受影响的行数return result;} catch (SQLException ex) {// 回滚事务DataSourceUtils.rollbackIfNecessary(con, getDataSource());throw translateException(Callback, getSql(action), ex);} finally {DataSourceUtils.releaseConnection(con, getDataSource());}
}// 执行给定的 SQL 语句和参数返回查询结果
public T T query(final String sql, final ResultSetExtractorT rse, Object... args) throws DataAccessException {Assert.notNull(sql, SQL must not be null);Assert.notNull(rse, ResultSetExtractor must not be null);// 匿名内部类实现 ConnectionCallback 接口return execute(new ConnectionCallbackT() {Overridepublic T doInConnection(Connection con) throws SQLException {PreparedStatement ps null;ResultSet rs null;try {// 创建 PreparedStatement 对象ps createPreparedStatement(con, sql);// 设置 PreparedStatement 的参数setValues(ps, args);// 执行查询返回结果集rs ps.executeQuery();// 对结果集进行处理返回查询结果return rse.extractData(rs);} finally {JdbcUtils.closeResultSet(rs);JdbcUtils.closeStatement(ps);}}}, true);
}4. 运用模板方法手写简单版JdbcTemplate
定义DefineJcbcTemplate自定义jdbcTemplate接口
public interface DefineJcbcTemplate {T T queryForObject(String sql, DefineRowMapperT defineRowMapper);
}定义DefineRowMapper函数式接口回调作用处理jdbc查询结果ResultSet返回泛型T对象
FunctionalInterface
public interface DefineRowMapperT {T mapRow(ResultSet rs) throws SQLException;
}DefineJcbcTemplateImpl实现类该实现类的连接数据库、释放资源等操作都是从步骤一复制粘贴进来的唯一不同的是把处理结果解耦出来了定义好处理结果的接口DefineRowMapper交由调用者去实现对结果的处理最后回调该接口的方法mapRow并返回结果其他的把连接数据库、释放资源封装起来这样一来不用每次进行数据库查询都需要连接数据库、释放资源。
Service
public class DefineJcbcTemplateImpl implements DefineJcbcTemplate {Autowiredprivate DataSource dataSource;Overridepublic T T queryForObject(String sql, DefineRowMapperT defineRowMapper) {// 一部分是准备和释放资源以及执行 SQL 语句另一部分则是处理 SQL 执行结果Connection connection null;PreparedStatement preparedStatement null;ResultSet resultSet null;try {// 创建dataSource,获取连接connection dataSource.getConnection();// 执行查询preparedStatement connection.prepareStatement(sql);// 获取执行结果resultSet preparedStatement.executeQuery();// 交由调用者去实现对结果的处理return defineRowMapper.mapRow(resultSet);} catch (Exception e) {e.printStackTrace();} finally {// 关闭资源if (preparedStatement ! null) {try {preparedStatement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection ! null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}return null;}
}调用自定义模板方法进行数据库查询
RunWith(SpringRunner.class)
SpringBootTest(classes TestSpringTemplateApplication.class)
public class TestSpringTemplateApplicationTests {Autowiredprivate DefineJcbcTemplate defineJcbcTemplate;Testpublic void testQueryForObject() {// 定义sqlString sql SELECT * FROM user;// 通过模版方法进行查询ListUser users defineJcbcTemplate.queryForObject(sql, (rs) - {ListUser result new ArrayList();while (rs.next()) {// 遍历ResultSet并封装成集合User user new User();user.setId(rs.getInt(id));user.setName(rs.getString(name));user.setEmail(rs.getString(email));result.add(user);}return result;});System.out.println(users);}
}通过上面的代码您可以看到模板方法模式可以很容易地将重复的部分代码提取到父类中而将可变的部分代码放入子类中从而实现代码的复用和扩展。