Template Method Pattern——模板方法模式
设计原则:不要重复
- DRY(Don’t Repeat Yourself,不要复制自己)
- OAOO(Once and Only once,仅此一次):避免代码重复
GOF给出的模板方法模式定义如下:
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redifine certain steps of an algorithm without changing the algorithm’s structure.
定义在一个操作中的一个算法框架,把一些步骤推迟到子类中去实现。模板方法模式让子类不需要改变算法结构而重新定义特定的算法步骤。
也就是说模板方法定义了一系列算法步骤,子类可以去实现/覆盖其中某些步骤,但不能改变这些步骤的执行顺序,模板方法有如下功能:
- 能够解决代码冗余问题
- 把某些算法步骤延迟到子类,子类可以实现自己的特性
- 易于扩展,通过新类继承父类即可
示例代码一:回家过年步骤模拟
public abstract class HappyPeople{ //模板类
public void happyNewYear(){ //定义执行顺序
bookTicket(); //订票
travle(); //返程
celebrate(); //庆祝
}
protected void bookTicket(){ //......}
protected abstract void travel(); //模板方法,留给子类延迟重写的方法
protected void celebrate(){ //......}
}
----------------------------------------------------
public class PassengerByBus extends HappyPeople{ //子类一,坐汽车回家
@Override
protected void travel(){
System.out.println("Travel By BUS!")
}
}
------------------------------------------------------
public class PassengerByAir extends HappyPeople{ //子类二,坐飞机回家
@Override
protected void travel(){
System.out.println("Travel By AIR!")
}
}
------------------------------------------------------
示例代码一尽可能避免了冗余代码的出现,例如模板类中的bookTicket()、celebrate()等没有任何改变的代码。但是,随着乘客出行方式的增多,就会使得子类的个数泛滥。可以通过引入回调(CallBack)来避免子类个数的增多。
实例代码二:数据库结果集处理示例
public interface ResultSetHandler<T>{ //定义结果集处理接口
public T handle(ResultSet rs);
}
---------------------------------------
public class SimpleJdbcQueryTemplate{
public <T>T query(String queryString,ResultSetHandler<T> rsHandler){ //在查询方法中引入ResultSetHandler作为参数并调用handle()方法
connection=getConnnection();
stmt=connection.prepareStatement(queryString);
ResultSet rs=stmt.executeQuery();
return rsHanlder.handle(rs); //调用结果集处理接口
}
}
//测试模板
public void testTemplate(){
boolean called=new SimpleJdbcQueryTemplate().query("select * from db",
new ResultSetHandler<Boolean>(){ //回调通过匿名内部类实现
public Boolean handle(ResultSet rs){
//处理结果集的代码
return Boolean.TRUE;
}
}
);
assertTrue(called);
}
通过回调实现模板方法模式,可以避免子类数量的泛滥。此模式在Spring框架里使用十分广泛,可以通过查看源码发现。