模板方法模式(TemplateMethod)定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
当我们要完成在某一细节层次一致的一个过程或一系列步骤,担其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法模式来处理,模板方法模式通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。
UML图
AbstractClass是抽象类,其实也就是一抽象模板,定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现,顶级逻辑也有可能调用一些具体方法。
举例
我们都知道,装修房屋的过程分为水电泥木油,现有一支施工队,为A、B两座房屋装修。假设因房屋大小不同,水、电、泥工的工程量不同,但木工与油漆工由于特殊原因,工程量是固定的。因此我们需要将水电泥的方法延迟到具体的房屋施工子类中去实现,而固定的木工与油漆工,可以提取到抽象父类中来。
先看装修的抽象父类:
public abstract class Decorate {
/**
* 施工
*/
public void Construct(){
waterConstruction();
electricConstruction();
mudConstruction();
System.out.println("木工耗时10天");
System.out.println("油漆工耗时15天");
System.out.println(getHouseName() + "的房屋装修结束!");
}
//定义一些抽象行为,放到子类中去实现
public abstract void waterConstruction(); //水
public abstract void electricConstruction(); //电
public abstract void mudConstruction(); //泥
public abstract String getHouseName(); //获取房屋户主名
}
小房子的装修类:
public class HouseA extends Decorate{
@Override
public void waterConstruction() {
System.out.println("水工耗时5天");
}
@Override
public void electricConstruction() {
System.out.println("电工耗时6天");
}
@Override
public void mudConstruction() {
System.out.println("泥工耗时7天");
}
@Override
public String getHouseName() {
return "pzx";
}
}
大房子的装修类:
public class HouseB extends Decorate {
@Override
public void waterConstruction() {
System.out.println("水工耗时8天");
}
@Override
public void electricConstruction() {
System.out.println("电工耗时10天");
}
@Override
public void mudConstruction() {
System.out.println("泥工耗时10天");
}
@Override
public String getHouseName() {
return "zyb";
}
}
调用
public static void main(String[] args){
Decorate decorate;
decorate = new HouseA();
decorate.Construct();
decorate = new HouseB();
decorate.Construct();
}
输出
水工耗时5天
电工耗时6天
泥工耗时7天
木工耗时10天
油漆工耗时15天
pzx的房屋装修结束!
水工耗时8天
电工耗时10天
泥工耗时10天
木工耗时10天
油漆工耗时15天
zyb的房屋装修结束!
可以看到,当不变和可变的行为在方法的子类实现中混合在一起时,不变的行为就会在子类中重复出现,我们可以通过模板方法模式把这些行为搬到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。