概念
模板方法在书中的定义就是:定义一个操作中流程的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。(也因此, 模板方法是基于继承的)
通俗而言,完成一件事情会有很多步骤,但这些步骤是固定的,只是不同的人不同的对象的步骤实现不同
举个栗子
常见的炒菜,流程简单地写分为如下几个步骤,洗菜、放油、炒菜、加调料、盛出
abstract class Cook{
//洗菜、放油、盛出的动作都一样所以实现在父类中,父类定义了动作的步骤
public void doCook(){
wash();
oil();
fry();
addSauce();
carriedDishes();
}
public void wash(){
System.out.println("washing...");
}
public void oil(){
System.out.println("put oil...");
}
abstract void fry();
abstract void addSauce();
public void carriedDishes(){
System.out.println("carry dishes...");
}
}
public class MyCook_1 extends Cook(){
@Override
public void fry(){
System.out.println("my cook 1");
}
@Override
public void addSauce(){
System.out.println("my add sauce 1");
}
}
//main方法中实例化MyCook_1调用doCook()即可
解决的问题
- 提高复用性,公有的共同的方法在父类已经实现
- 提高拓展性,真正的实现由子类完成,子类的实现细节不会改变父类的流程
- 反向控制,父类调用子类的方法,子类具体实现拓展不同的行为,符合“开闭原则”
缺点
- 每一个实现都需要增加一个子类,系统会很庞大
使用场景
模板方法简单但是却很常见,好比如数据库的增删改查可以自定义模板
public abstract class AbstractDao {
//查询操作,由于统一的数据库索引操作一样,所以抽出来放到父类中,而rowMapper则放在子类中实现,因为不同的子类有不同的行映射
protected Object find(String sql, Object[] params) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Object obj = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
rs = ps.executeQuery();
while (rs.next()) {
obj = rowMapper(rs);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.free(rs, ps, conn);
}
return obj;
}
protected abstract Object rowMapper(ResultSet rs) throws SQLException;
//同时可以添加 insert ,update 等方法
}
网友评论