1、模板方法模式
模板方法模式(Template Method Pattern)
,又称为模板模式,它属于行为型设计模式。
是指定义一个操作中算法的骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下即可重定义该算法的某些特定步骤。
模板方法模式实际上封装了一个固定流程,该流程有几个步骤组成,具体步骤可以由子类进行不同的实现。
2、模板方法模式的结构
模板方法模式需要注意抽象类与具体子类之间的协作。
它用到了虚函数的多态性技术以及“不用调用我,让我来调用你”的反向控制技术。
1. 模板方法模式包含以下主要角色:
(1)抽象类/抽象模板(Abstract Class)
抽象模板类,负责给出一个算法的轮廓和骨架。
它由一个模板方法和若干个基本方法构成。这些方法的定义如下:
(2)具体子类/具体实现(Concrete Class)
具体实现类,实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
3、优缺点
主要优点:
主要缺点:
4、使用场景
算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。
当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展。
注意事项
:一般模板方法都加上 final
关键字,避免子类对其覆写,防止其恶意操作。
模板方法模式的代码如下:
public class TemplateMethodPattern {
public static void main(String[] args) {
AbstractClass tm = new ConcreteClass();
tm.TemplateMethod();
}
}
//抽象类
abstract class AbstractClass {
//模板方法
public final void TemplateMethod() {
SpecificMethod();
abstractMethod1();
abstractMethod2();
}
//具体方法
public void SpecificMethod() {
System.out.println("抽象类中的具体方法被调用...");
}
//抽象方法1
public abstract void abstractMethod1();
//抽象方法2
public abstract void abstractMethod2();
}
//具体子类
class ConcreteClass extends AbstractClass {
@Override
public void abstractMethod1() {
System.out.println("抽象方法1的具体实现被调用...");
}
@Override
public void abstractMethod2() {
System.out.println("抽象方法2的具体实现被调用...");
}
}
用一个做饭的例子来说明。简单地定义一下步骤(模板方法):
1、抽象父类
public abstract class AbstractCook {
public final void doCook(){
openFire();
cooking();
closedFire();
}
protected abstract void cooking();
protected void openFire() {
System.out.println("点火,开始做菜了");
}
protected void closedFire() {
System.out.println("关火,菜出锅了");
}
}
2、具体子类
public class Crayfish extends AbstractCook {
@Override
protected void cooking() {
System.out.println("一份小龙虾!");
}
}
public class FryRice extends AbstractCook {
@Override
protected void cooking() {
System.out.println("一份炒饭!");
}
}
3、测试
public class TemplateMethodPatternTest {
public static void main(String[] args) {
AbstractCook crayfish = new Crayfish();
crayfish.doCook();
System.out.println("===========");
FryRice fryRice = new FryRice();
fryRice.doCook();
}
}
钩子方法的主要目的:
目的是干预执行流程,正确使用钩子方法可以使得子类控制父类的行为。
做饭的例子改造下,给饭菜加上口味。简单地定义一下步骤(模板方法):
1、抽象父类
public abstract class AbstractCook {
public final void doCook(){
openFire();
cooking();
if(isTasteHookMethod()){
taste();
}
closedFire();
}
//钩子方法1
public boolean isTasteHookMethod() {
return false;
}
protected void taste(){
}
protected abstract void cooking();
protected void openFire() {
System.out.println("点火,开始做菜了");
}
protected void closedFire() {
System.out.println("关火,菜出锅了");
}
}
2、具体子类
public class Crayfish extends AbstractCook {
@Override
protected void cooking() {
System.out.println("一份小龙虾!");
}
@Override
public boolean isTasteHookMethod() {
return true;
}
@Override
protected void taste() {
System.out.println("麻辣味的,多放辣!");
}
}
public class FryRice extends AbstractCook {
@Override
protected void cooking() {
System.out.println("一份炒饭!");
}
}
模板方法模式在框架源码中使用也很广泛,比如:
—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。