java组件 模式_java设计模式--模板模式

模板模式

通常又叫模板方法模式,定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现.

​ 模板方法使得子类可以再不改变算法结构的情况下,重新定义算法的某些步骤. 是行为型设计模式.

适用场景

一次性实现一个算法的不变部分,将可变的行为留给子类来实现;

各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复;

常见的应用:AbstractList、HttpServlet的service方法、Spring的 JdbcTemplate、Tomcat的架构中.

模仿JdbcTemplate的模板模式

​ 简单模仿Spring的JdbcTemplate ,JDBC操作可以理解为有流程的,可以复制的.最开始学习JDBC操作时:打开连接 → 获取语句集 → 设置参数、执行语句集 → 处理结果集 → 关闭连接 .

JdbcTemplate代码

package com.template;

import javax.sql.DataSource;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

public class JdbcTemplate {

private DataSource dataSource;

public JdbcTemplate(DataSource dataSource){this.dataSource=dataSource;}

public List executeQuery(String sql,Object[] args,RowMapper rowMapper){

PreparedStatement ps=null;

Connection connection=null;

try {

//1.获取连接

connection =this.getConnection(dataSource);

//2.获得语句集

ps = createPreparedStatement(connection, sql);

//3.执行语句集得到ResultSet

ResultSet rs=doExecuteQuery(ps,args);

//4.处理结果集

List result = parseResultSet(rs,rowMapper);

return result;

}catch (Exception e){

e.printStackTrace();

}finally {

//5.释放资源.

closePreparedStatement(ps);

closeConnection(connection);

}

return null;

}

private void closeConnection(final Connection connection) {

try {

connection.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

private void closePreparedStatement(final PreparedStatement ps) {

try {

ps.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

private List parseResultSet(final ResultSet rs, final RowMapper rowMapper) throws Exception {

List result=new ArrayList<>();

int rowNum=1;

while(rs.next()){

result.add(rowMapper.mapperRow(rs,rowNum++));

}

return result;

}

private ResultSet doExecuteQuery(final PreparedStatement ps, final Object[] args) throws SQLException {

for (int i=0;i

ps.setObject( i+1,args[i]);

}

return ps.executeQuery();

}

private PreparedStatement createPreparedStatement(Connection connection,String sql) throws SQLException {

return connection.prepareStatement(sql);

}

protected Connection getConnection(final DataSource dataSource) throws SQLException {

return dataSource.getConnection();

}

}

RowMapper接口

RowMapper接口可以理解为是 钩子,用来在JdbcTemplate模板方法处理结果集时使用.

package com.template;

import java.sql.ResultSet;

public interface RowMapper {

T mapperRow(ResultSet rs,int rowNum) throws Exception;

}

UserDao测试效果

package com.template;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;

import java.sql.ResultSet;

import java.util.List;

public class UserDao extends JdbcTemplate {

private static final Object[] EMPTY_ARGS=new Object[0];

public UserDao(final DataSource dataSource) {

super(dataSource);

}

public List selectAll(){

String sql="select * from user";

return super.executeQuery(sql, EMPTY_ARGS, new RowMapper() {

@Override

public User mapperRow(final ResultSet rs, final int rowNum) throws Exception {

User user = new User();

user.setId(rs.getInt("id"));

user.setName(rs.getString("name"));

user.setAge(rs.getInt("age"));

user.setSex(rs.getString("sex"));

return user;

}

});

}

public static void main(String[] args) throws Exception {

Class.forName("com.mysql.jdbc.Driver");

ComboPooledDataSource dataSource = new ComboPooledDataSource();

dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");

dataSource.setDriverClass("com.mysql.jdbc.Driver");

dataSource.setUser("root");

dataSource.setPassword("yourPassword");

UserDao dao = new UserDao(dataSource);

List users = dao.selectAll();

for(User user:users){

System.out.println(user);

}

}

}

代码测试效果

007Sw1e1ly1g4slova7jej31d7063q3f.jpg

优点

提高代码复用、扩展性,符合开闭原则

缺点

增加系统复杂度 ;父类添加抽象方法,所有子类都需要重写抽象方法;

框架中常见的模板方法

1.JDK中 AbstractList.get

007Sw1e1ly1g4sm0h08tnj30h00403yg.jpg

常见的ArrayList、Vector就是AbstractList的实现,ArrayList返回数组中的index下标的元素.

007Sw1e1ly1g4sm29y6i2j30ce035744.jpg

Servlet-api中

service方法继续调用service(HttpServletRequest,HttpServletResponse)方法,进一步根据请求方法来决定调用doGet、doPost等,我们以前开发时候写Servlet,有时候重写doGet、doPost方法来.

007Sw1e1ly1g4sm7byd8aj30jz0a5jrn.jpg

​ 上面的例子,你可能觉得模板方法只是实现抽象方法,但是在Tomcat中模板方法的使用可以说是非常精妙了.

Tomcat中

Tomcat几大组件 Server、Service、Engine、Host、Context、Connector都继承了LifecycleBase抽象类.

007Sw1e1gy1g4tbtxgrryj30wf07w0sv.jpg

LifecycleBase的init、start、stop、destroy都采用了模板方法,其中以init方法为例分析:

public final synchronized void init() throws LifecycleException {

if (!state.equals(LifecycleState.NEW)) {

//组件初始化前判断状态是否是新生NEW的

invalidTransition(Lifecycle.BEFORE_INIT_EVENT);

}

try {

//设置组件状态进入 `开始初始化之前`

setStateInternal(LifecycleState.INITIALIZING, null, false);

//不同组件采用不同实现,来完成组件的初始化

initInternal();

//组件状态设置为 初始化结束

setStateInternal(LifecycleState.INITIALIZED, null, false);

} catch (Throwable t) {

ExceptionUtils.handleThrowable(t);

setStateInternal(LifecycleState.FAILED, null, false);

throw new LifecycleException(

sm.getString("lifecycleBase.initFail",toString()), t);

}

}

//不同组件的初始化具体逻辑需要重写

protected abstract void initInternal() throws LifecycleException;

所以,Tomcat每个组件一般都会重写 initInternal、startInternal等模板方法,代码看起来完全不冗余,也符合开闭利于扩展新的组件.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值