首先,先声明一下,我是一名学生,代码行屈指可数,所谈之处只是个人的见解,错的地方希望大家多多指点,先谢谢大家~
大三一次很幸运的机会,参加了一次外面培训,当时的老师提到了一个概念就是:面向接口编程。但是当时老师因为时间的问题,没有展开给我们讲解,只是让我们看了一下他的应用,后来自己多次模仿。其实,操作很简单,当你想建立一个类的时候,就把类中公有的方法抽象到接口中,然后定义一个名字。
有一天,我发现这个过程很麻烦,因为每次我要修改参数的时候,都要先修改接口,然后再修改类,而我这个接口貌似只是针对这一个类的,如果没有它,我的这个程序是依然可以完成的,然后,我毅然决然的就不再使用接口了。后来,才知道是自己没有真正理解“面向接口编程”的真正意义。
大三的下学期,依然是去参加培训,这次时间比较短暂,所接触的知识就是由java到web的学习——jsp的简单应用。关于知识没有学到多少,但是老师在整个过程中,一直给我们强调了一个关于编程过程的问题,后来老师提到了一本叫“重构”的书。对于编码,首先应该是想办法把问题解决,然后把看得不舒服的位置,仔细思考,然后进行修改,更换些简便舒服的代码段。
实习结束之后,自己厚着脸皮买了这本叫“重构——改善既有代码的设计”,为什么说厚着脸,因为总觉得只有代码行达到一定量之后,才能完成代码的优化美观。后来自己读了,书上介绍的过程也大致就是老师讲解的意思,因为自己的能力有限还没有真正理解书中的高深技术,但是在自己编程中,有的时候自己也略微整理一下自己的代码,慢慢的,我发现自己喜欢上abstract class这个东西了,每次结构相似的抽象一下整理出一个父类,然后把其中的代码分功能模块的整理。
随着编码越来越多,自己开始频繁的使用数据库,大家也都知道,在数据库连接中,更新操作,代码的样子都差不多,每次不同的只是从数据库中查找对象,于是自己写了一个这样的抽象类,以供不同的实体类继承。
/**
* 数据库连接
*/
protected Connection conn = null;
/**
* 数据库操作
*/
protected Statement stmt = null;
/**
* 数据库预编译操作
*/
protected PreparedStatement pstmt = null;
/**
* 结果集
*/
protected ResultSet rs = null;
/**
* 从结果集中获取信息
* @function:从结果集中读取一条信息,并以实例的格式返回
* @return 对象实例
* @author: 艳沐石 2010-10-17 下午02:13:09
* @throws SQLException
*/
protected abstract E getInfoFromResultSet() throws SQLException;
/**
* 获得简单的数据库查询语句
* @return
*/
protected abstract String createBaseQuerySql();
/**
* 查询信息集合
* @function:使用Statement操作,将满足条件的信息以集合的形式返回
* @param sql 数据库语句
* @return 查询结果的集合
* @author: 艳沐石 2010-10-17 下午02:14:17
*/
public List<E> getAllInfosByStatement(String sql) {
List<E> list = new ArrayList<E>();
try {
getResultSetByStatement(sql);
// 将结果集中的数据读取出来,存入到集合中
while (rs.next()) {
list.add(getInfoFromResultSet());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBConnection.close(rs, stmt, conn);
}
return list;
}
/**
* 从结果集中读取一条信息
* @function:使用Statement操作,读取符合条件的第一条信息
* @param sql 数据库语句
* @return 对象实例
* @author: 艳沐石 2010-10-17 下午02:15:15
*/
public E getInfoByStatement(String sql) {
E e = null;
try {
getResultSetByStatement(sql);
// 读取获得结果信息
if (rs.next()) {
e = getInfoByStatement(sql);
}
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
DBConnection.close(rs, stmt, conn);
}
return e;
}
/**
* 查询信息集合
* @function:使用PreparedStatment操作,将满足条件的信息以集合的形式返回
* @param sql 数据库语句
* @param values 限制条件的值
* @return 信息集合
* @author: 艳沐石 2010-10-17 下午02:16:37
*/
public List<E> getAllInfosByPreparedStatement(String sql, List<Object> values) {
List<E> list = new ArrayList<E>();
try {
getResultSetByPreparedStatement(sql, values);
// 将结果集中的信息添加到集合中
while (rs.next()) {
list.add(getInfoFromResultSet());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBConnection.close(rs, pstmt, conn);
}
return list;
}
/**
* 从结果集中读取一条信息
* @function:使用PreparedStatement操作,读取一条满足条件的信息,以实例形式返回
* @param sql 数据库语句
* @param values 限制条件的值
* @return 对象实例
* @author: 艳沐石 2010-10-17 下午02:18:04
*/
public E getInfoByPreparedStatement(String sql, List<Object> values) {
E e = null;
try {
getResultSetByPreparedStatement(sql, values);
if (rs.next()) {
e = getInfoFromResultSet();
}
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
DBConnection.close(rs, pstmt, conn);
}
return e;
}
/**
* 数据库更新
* @function:使用Statement操作,更新数据库信息
* @param sql 数据库语句
* @return 受影响的行数
* @author: 艳沐石 2010-10-17 下午02:19:25
*/
public int updateInfosByStatement(String sql) {
int count = 0;
try {
confStatement();
// 执行更新,并记录影响行数
count = stmt.executeUpdate(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBConnection.close(stmt, conn);
}
return count;
}
/**
* 数据库更新
* @function:使用PreparedStatement操作,更新数据库信息
* @param sql 数据库语句
* @param values 限制条件的值
* @return 受影响的行数
* @author: 艳沐石 2010-10-17 下午02:20:30
*/
public int updateInfosByPreparedStatement(String sql, List<Object> values) {
int count = 0;
try {
confPreparedStatement(sql, values);
// 执行更新,并记录影响行数
count = pstmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBConnection.close(pstmt, conn);
}
return count;
}
/**
* 批处理更新数据库
* @function:处理一批数据库更新操作
* @param sqls 数据库语句组(数组)
* @return 每条更新所影响的数据库行数
* @author: 艳沐石 2010-10-17 下午02:22:31
*/
public int[] updateInfosByStatementBatch(String[] sqls) {
int[] count = null;
try {
confStatement();
// 将需要执行的语句添加到批处理操作中
for (String sql : sqls) {
stmt.addBatch(sql);
}
// 批处理执行
count = stmt.executeBatch();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
DBConnection.close(stmt, conn);
}
return count;
}
/**
* 批处理更新数据库
* @function:处理一批数据库更新操作
* @param sqls 数据库语句组(集合)
* @return 每条更新所影响的数据库行数
* @author: 艳沐石 2010-10-17 下午02:24:27
*/
public int[] updateInfosByStatementBatch(List<String> sqls) {
return updateInfosByStatementBatch((String[])sqls.toArray());
}
/**
* 获得结果集
* @function:使用Statement操作,获取查询的结果集
* @param sql 数据库语句
* @throws SQLException 数据库操作异常
* @author: 艳沐石 2010-10-17 下午02:25:41
*/
protected void getResultSetByStatement(String sql) throws SQLException {
confStatement();
rs = stmt.executeQuery(sql);
}
/**
* 获得结果集
* @function:使用PreparedStatement操作,获取查询的结果集
* @param sql 数据库语句
* @param values 限制条件的值
* @throws SQLException 数据库操作异常
* @author: 艳沐石 2010-10-17 下午02:26:21
*/
protected void getResultSetByPreparedStatement(String sql, List<Object> values) throws SQLException {
confPreparedStatement(sql, values);
rs = pstmt.executeQuery();
}
/**
* 配置Statement操作
* @function:连接数据库,并获得数据库操作
* @throws SQLException 数据库操作异常
* @author: 艳沐石 2010-10-17 下午02:27:02
*/
protected void confStatement() throws SQLException {
confConnectiong();
stmt = conn.createStatement();
System.out.println(stmt);
}
/**
* 配置PreparedStatement操作
* @function:连接数据库,并将生成预编译处理操作
* @param sql 数据库语句
* @param values 限制条件的值
* @throws SQLException 数据库操作异常
* @author: 艳沐石 2010-10-17 下午02:27:30
*/
protected void confPreparedStatement(String sql, List<Object> values) throws SQLException {
confConnectiong();
pstmt = conn.prepareStatement(sql);
if (values != null) {
for (int i = 0; i < values.size(); i++) {
pstmt.setObject(i+1, values.get(i));
}
}
System.out.println(pstmt);
}
/**
* 配置数据库连接
* @function:获得一个数据库连接
* @author: 艳沐石 2010-10-17 下午02:29:00
*/
protected void confConnectiong() {
conn = DBConnection.getConnection();
}
}
这样,当我对不同的实体类就可以是指实现getInfoFromResultSet方法了。
随着时光的推进,在大四,我接触到了流行的SSH框架,大三下学期的时候,同学就鼓励我看看框架,可是自己总觉得自己基础知识还没到位,于是自己学习了关于设计模式,编程规范,重构等方面的东西,自己觉得自己还是有些收获,但是跟自己代码行还是有很大的关系。自己也写了几个关于Spring的程序,这个时候,只是知道Spring大量使用面向接口编程,自己也没太明白。后来,同学给自己介绍的时候,我依然觉得不用接口也可以啊,后来自己还专门写了一个抽象类,以用来减少代码的冗余:
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public abstract class AbstractService<E> {
protected SessionFactory sessionFactory = null;
/**
* @return the sessionFactory
*/
public SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* @param sessionFactory the sessionFactory to set
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* @return 获得当前会话
*/
public Session getSession() {
return getSessionFactory().getCurrentSession();
}
/**
* @param hql 需要执行的hql语句
* @return the query 封装好的Query对象
*/
public Query getQuery(String hql) {
return getSession().createQuery(hql);
}
/*
* 根据id获得信息
*/
public abstract E getInfo(int id);
/*
* 批量获取信息
*/
public abstract List<E> getInfos(int currentPage, int pagesize);
/*
* 根据id删除
*/
public void delete(int id) {
getSession().delete(id);
}
/*
* 保存
*/
public void save(E e) {
getSession().save(e);
}
/*
* 更新
*/
public void update(E e) {
getSession().update(e);
}
/**
* @param q the query
* @param currentPage the current page num
* @param pagesize the count of a page
*/
protected void confQuery(Query q, int currentPage, int pagesize) {
q.setFirstResult(firstLocation(currentPage, pagesize));
q.setMaxResults(pagesize);
}
/**
* @param q the query
* @return the result list
*/
@SuppressWarnings("unchecked")
protected List<E> list(Query q) {
List<E> list = q.list();
return list;
}
/*
* get the first record location
*/
private int firstLocation(int currentPage, int pagesize) {
return (currentPage - 1) * pagesize;
}
}
最近,自己在一次与具有丰富经验的前辈聊天的时候,谈到了面向接口编程这个概念,也是通过他的讲解,自己发现,自己存在着很大的问题。所谓的面向接口编程,就像盖房子似的,接口是房屋的架子,而架子里放的东西是什么,也就是实现这个架子的类,我们像摆积木一样的,把自己需要的实现类放到指定的位置,这也就是Spring配置文件的意思,当有一天,我们需要升级系统的时候,有些实现类过时了,不再需要的时候,我们只需要把新的实现类替换旧的实现类,这样,每次修改,都只需要做小幅度的调整。而面向接口编程的一个重要目的不是为了首次开发带来方便的,而是为以后维护带来方便的。
仔细思考,发现自己在编程的思想上还很幼稚,对于抽象类,我完全可以把他抽象一个接口,当作一个工具对象,聚合到另外的类中,这样我也可以维护这个工具类了。
突然想到了thingking in java第一章的标题:一切都是对象。
加油,努力!