利用组合方法模式重构方法,组合方法模式,要求所有的共有方法读起来像一系列执行步骤的概要,而这些步骤的真正实现细节是在私有方法里面。下面看一段没有用组合方法模式去重构过的代码片段:
public void populate() throws ClassNotFoundException, SQLException{
List partList = new ArrayList();
Connection connection = null;
String driverClass = “com.mysql.jdbc.Driver”;
String url = “jdbc:mysql://localhost:3306/test?user=root&password=root&useUnicode=true&characterEncoding=utf-8”;
String user = “root”;
String password = “root”;
String sql = “select istaffid,sstaffname from staff”;
try{
Class.forName(driverClass);
connection = DriverManager.getConnection(url, user, password);
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
Part p = new Part();
p.setName(rs.getString(“name”));
p.setBrand(rs.getString(“brand”));
p.setRetailPrice(rs.getDouble(“retailPrice”));
partList.add(p);
}
}finally{
connection.close();
}
}
这段代码很简单,从数据库中获取连接、查库、循环结果集并把相应字段设到Part对象中,最后把Part对象放到partList中。整段代码的工作流程非常简单,运行起来也没发现什么问题,但是这样就代表代码没有问题了吗?作为一个开发人员,不应该就这点要求,代码能运行不报错就算完成,而应该是尽量写出质量更高,更健壮的代码。像以上的代码复用性非常差,在方法内连接数据库,这样要是其它的方法也要连接数据库,也得写一遍类似的连接数据库代码,显然会增加系统的重复代码。因此以上方法可以进行重构。
刚才的代码片段,可以按照组合方法进行重构:
把获取数据库连接的代码抽取到一个方法中:
private Connection getConnection() throws SQLException, ClassNotFoundException{
String driverClass = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test?user=root&password=root&useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "root";Class.forName(driverClass);
return DriverManager.getConnection(url, user, password);
}
接着可以抽取获取结果集的代码到一个方法中:
private ResultSet getResultSet(Connection connection) throws SQLException, ClassNotFoundException{
Statement stmt = connection.createStatement();
return stmt.executeQuery(sql);
}
循环结果集对Part对象设置也可以抽取到一个方法中:
private void addEntryToListFromResultSet(ResultSet rs) throws SQLException{
Part p = new Part();
p.setName(rs.getString("name"));
p.setBrand(rs.getString("brand"));
p.setRetailPrice(rs.getDouble("retailPrice"));
partList.add(p);
}
然后populate方法可以这样调用刚才抽取的方法:
public void populate() throws ClassNotFoundException, SQLException{
Connection connection = null;
try{
connection = getConnection();
ResultSet rs = getResultSet(connection);
while(rs.next()) addEntryToListFromResultSet(rs);
}finally{
connection.close();
}
}
现在populate方法看上去简洁多了,而且易读性更高,这样就符合组合方法模式的原则了-共有方法读起来像一系列执行步骤的概要,而这些步骤的真正实现细节是在私有方法里面。
但是重构到这里还不算太好,因为现在的数据库连接还在populate方法所在的类内,要是这样要做到很好的代码复用,那么子类就需要继承populate方法所在的类,但是这样不太适合,因为populate方法所在的类或者还有其它逻辑。所以我们应该把数据库相关的操作(getConnection()、getResultSet())抽取到父类中,populate()方法也可以利用模板方法模式抽取到父类,这样子类只要继承抽取出来的父类,就可以对数据库进行操作,而子类就可以实现自己的逻辑。