概述
模板方法模式是一种行为设计模式,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以重定义某些步骤,而不改变算法的结构。这种模式是基于“好莱坞原则”(Don't Call Us, We'll Call You),即父类控制子类的行为,而不是子类主动调用父类的方法。
目的
代码复用:通过在一个抽象类中定义算法的框架,可以让子类在不修改算法结构的情况下重用该算法。
灵活性:允许子类对算法的某些部分进行定制,以适应不同的需求。
封装不变性:将不变的部分封装在父类中,变化的部分委托给子类实现,提高了代码的可维护性。
结构
抽象类(Abstract Class):定义了一个或多个抽象操作,以及一个模板方法。模板方法定义了算法的骨架,并调用抽象操作来完成算法的具体步骤。
具体子类(Concrete Class):实现父类所定义的一个或多个抽象操作,没有修改模板方法的权限,但可以通过覆盖抽象操作来影响算法的行为。
代码示例
假设我们有一个制作咖啡的场景,基本的咖啡制作流程是固定的(烧水、冲泡、添加调料),但不同种类的咖啡可能需要添加不同的调料。这里就可以使用模板方法模式来设计。
// 抽象类:咖啡制作过程的模板
abstract class CoffeeMaker {
// 模板方法,定义了制作咖啡的步骤
public final void makeCoffee() {
boilWater();
brewCoffeeGrinds();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
// 具体步骤,由子类实现
protected abstract void addCondiments();
// 具体步骤,子类可以重写但通常不需要
protected void boilWater() {
System.out.println("Boiling water");
}
protected void brewCoffeeGrinds() {
System.out.println("Brewing coffee grinds");
}
protected void pourInCup() {
System.out.println("Pouring into cup");
}
// 钩子方法,子类可以决定是否需要调料
protected boolean customerWantsCondiments() {
return true;
}
}
// 具体子类:美式咖啡
class Americano extends CoffeeMaker {
@Override
protected void addCondiments() {
System.out.println("Adding hot water");
}
}
// 具体子类:卡布奇诺
class Cappuccino extends CoffeeMaker {
@Override
protected void addCondiments() {
System.out.println("Adding milk and chocolate powder");
}
}
public class CoffeeShop {
public static void main(String[ ] args) {
CoffeeMaker coffee = new Americano();
coffee.makeCoffee();
System.out.println("\nMaking a Cappuccino...");
coffee = new Cappuccino();
coffee.makeCoffee();
}
}
适用场景
当多个类有相似的操作,但这些操作中的一部分在每个类中有不同的实现时。
当你需要控制子类的扩展方式,确保它们遵循特定的规则或模板时。
总结
模板方法模式提供了一种定义算法框架的方式,同时允许子类对算法的某些步骤进行定制。它通过将不变部分和可变部分分离,增强了代码的复用性和灵活性,同时也保证了算法的整体结构稳定,易于维护和扩展。
评论区