介绍
- 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
- 简单说,模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤
原理
对原理类图的说明-即(模板方法模式的角色及职责)
- AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法operationr2,3,4
- ConcreteClass 实现抽象方法operationr2,3,4, 以完成算法中特点子类的步骤
案例
编写制作豆浆的程序,说明如下:
- 制作豆浆的流程 选材—->添加配料—->浸泡—->放到豆浆机打碎
- 通过添加不同的配料,可以制作出不同口味的豆浆
- 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的
//抽象豆浆类,make方法是豆浆制作全过程,但addSome方法需要子类实现
public abstract class SoyMilk {
public final void make(){
select();
if (gouZi())
addSome();
soak();
broken();
}
public void select(){
System.out.println("第一步: 选择黄豆");
}
public abstract void addSome();
public void soak(){
System.out.println("第三步: 浸泡豆子");
}
public void broken(){
System.out.println("第四步: 放入豆浆机打碎");
}
protected boolean gouZi(){ //钩子函数,控制模板方法特定执行,子类重写,模板方法采用默认方式执行
return true;
}
}
public class HetaoSoyMilk extends SoyMilk{
@Override
public void addSome() {
System.out.println("第二步: 加入核桃");
}
}
public class YaoguoSoyMilk extends SoyMilk{
@Override
public void addSome() {
System.out.println("第二步: 加入腰果");
}
}
//纯豆浆不需要步骤二加配料,所以重写钩子方法,使得模板方法执行发生改变
public class PureSoyMilk extends SoyMilk{
@Override
public void addSome() {}
@Override
public boolean gouZi() {
return false;
}
}
public class Client {
public static void main(String[] args) {
SoyMilk SoyMilk1 = new HetaoSoyMilk();
SoyMilk1.make();
System.out.println("-----------------------------------------");
SoyMilk SoyMilk2 = new YaoguoSoyMilk();
SoyMilk2.make();
System.out.println("-------------------------------------------");
SoyMilk SoyMilk3 = new PureSoyMilk();
SoyMilk3.make();
}
}
模板方法模式的注意事项和细节
- 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算 法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改
- 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。
- 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现。
- 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大
- 一般模板方法都加上final关键字, 防止子类重写模板方法.
- 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤 ,这一系列的步骤基本相同,但其个别步骤在实现时 可能不同,通常考虑用模板方法模式来处理
个人总结
当多个对象需要实现的事情步骤基本相同只是具体实现不同时,可以使用一个抽象模板类定义模板方法,让子类实现模板类的各个步骤方法,客户端直接调用模板类的模板方法即可实现事情的完成。