1. 模板方法模式(Template Method)
模板方法模式是带有模板功能的模式,组成模板的抽象方法被定义在父类中,父类只负责管理子类可以调用哪些方法,而抽象方法的具体实习由子类完成,在子类中决定具体的处理流程。也就是说,在不同的子类中实现不同的具体处理,但无论子类中具体如何实现,处理的流程都会按照父类中定义的那样进行。
像这样在父类中定义处理流程的框架,在子类中实现具体处理的模式就称为Template Method模式。
1.1. 模式架构
- 抽象类(AbstractClass):抽象模板类负责给出算法的轮廓和骨架,它由一个模板方法和若干个基本方法构成。模板方法定义了整体的骨架,按某种顺序执行调用其包含的基本方法,基本方法的具体流程由具体子类实现。
- 具体类(ConcreteClass):负责实现抽象类中定义的抽象方法,这些方法会在抽象类中被调用。
1.2. 示例代码实现
场景:平常做饭时大致流程是有统一的模板的,具体的做饭流程一致,区别在于不同的菜有不同的处理工序,该业务就很适合使用模板方法模式。
抽象类(AbstractClass):
抽象模板类CookDiner
public abstract class CookDiner {
public abstract void WashFoods();//交给子类去实现抽象方法WashFoods
public abstract void CutFoods();//交给子类去实现抽象方法CutFoods
public final void Cook(){//本抽象类中实现的Cook方法,确定执行骨架和流程
WashFoods();
CutFoods();
//做饭
System.out.println("开始做饭");
}
}
具体类(ConcreteClass):
具体类Vegetables
public class Vegetables extends CookDiner {//Vegetables类是CookDiner类的子类
private String vegetName;
public Vegetables(String vegetName) {
this.vegetName = vegetName;
}
@Override
public void WashFoods() {//重写WashFoods方法,该方法会在Cook方法中被调用
System.out.println("开始洗:" + vegetName);
}
@Override
public void CutFoods() {//重写CutFoods方法,该方法会在Cook方法中被调用
System.out.println("开始切:" + vegetName);
}
}
具体类Meat
public class Meat extends CookDiner {//Meat类是CookDiner类的子类
private String meatName;
public Meat(String meatName) {
this.meatName = meatName;
}
@Override
public void WashFoods() {//重写WashFoods方法,该方法会在Cook方法中被调用
System.out.println("开始洗:" + meatName);
}
@Override
public void CutFoods() {//重写CutFoods方法,该方法会在Cook方法中被调用
System.out.println("开始切:" + meatName);
}
}
Main类:
public class Client {
public static void main(String[] args) {
//生成一个持有"黄瓜"的Vegetables类的实例
CookDiner cookVeget = new Vegetables("黄瓜");
//生成一个持有"牛肉"的Meat类的实例
CookDiner cookMeat = new Meat("牛肉");
//cookVeget、cookMeat都是CookDiner类的子类
cookVeget.Cook();//可以调用继承的Cook方法
cookMeat.Cook();//实际的程序行为取决于cookVeget类和cookMeat类的具体实现
}
}
执行结果:
开始洗:黄瓜
开始切:黄瓜
开始做饭
开始洗:牛肉
开始切:牛肉
开始做饭
在以上示例代码中,抽象模板类CookDiner定义了程序行为的框架和流程,父类通过Cook方法来按照流程处理方法,具体的方法由其子类Vegetables、Meat来实现。
与策略模式不同的是,模板方法模式会改变部分程序行为,而策略模式是用于替换整个算法。
1.3. 优缺点
优点:
- 代码复用:将公共代码抽取到模板方法中,避免重复实现。
- 扩展性:子类可以根据需要重写特定步骤,不影响算法整体结构。
- 结构清晰:算法框架清晰可见,易于理解和维护。
缺点:
- 固化框架:有时过度使用模板方法可能会导致框架过于固定,不利于灵活应对变化。
- 复杂度增加:可能会增加系统的复杂度,特别是当算法步骤较多、逻辑复杂时。
适用场景:
- 多个子类有共同的方法,并且逻辑基本相同:通过模板方法将这些共同的方法提取到父类中,避免重复代码。
- 需要控制子类的扩展:模板方法定义了算法的框架,子类只需实现特定的细节,而框架本身不变。