23 种设计模式中的模板模式

40 阅读2分钟

在父类中定义了算法的骨架,将某些步骤延迟到子类中,并允许子类在不改变算法结构的前提下重定义算法的某些特定步骤。

模板方法,主要的设计思想是,一个抽象的公开类定义了方法的框架。对于其中的一系列步骤,暂时确定不下来的步骤,就留给子类去实现好了。这样,不同的子类就可以定义不同的步骤。

这里我们根据案例来具体学习访问者模式。以下是一个代码示例及知识点详解。

假设我们要制作两种饮料:茶和咖啡。它们的制作过程有一些共同的步骤,但有一些步骤是不同的。我们可以使用模板方法来实现这个场景。

我们将创建一个定义操作的Beverage类,其中,模板方法定义为 final,这样它就不会被重写。TeaCoffee扩展了Beverage,它们重写了抽象类的方法。

定义抽象类Beverage

abstract class Beverage {
​
    // 模板方法,定义了制作饮料的算法框架
    public final void prepareBeverage() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }
​
    // 具体步骤,子类必须实现
    abstract void brew();
​
    abstract void addCondiments();
​
    // 具体步骤,子类可以选择覆盖
    boolean customerWantsCondiments() {
        return true;
    }
​
    // 具体步骤,通用方法
    void boilWater() {
        System.out.println("Boiling water");
    }
​
    void pourInCup() {
        System.out.println("Pouring into cup");
    }
}

定义实体类Tea

class Tea extends Beverage {
​
    @Override
    void brew() {
        System.out.println("Steeping the tea");
    }
​
    @Override
    void addCondiments() {
        System.out.println("Adding lemon");
    }
​
    @Override
    boolean customerWantsCondiments() {
        // 假设用户不喜欢加柠檬
        return false;
    }
}

定义实体类Coffee

class Coffee extends Beverage {
​
    @Override
    void brew() {
        System.out.println("Dripping coffee through filter");
    }
​
    @Override
    void addCondiments() {
        System.out.println("Adding sugar and milk");
    }
}

使用模板方法。

public class TemplateMethodDemo {
    public static void main(String[] args) {
        Beverage tea = new Tea();
        Beverage coffee = new Coffee();
​
        System.out.println("Making tea...");
        tea.prepareBeverage();
​
        System.out.println("\nMaking coffee...");
        coffee.prepareBeverage();
    }
}
  • Beverage 类中的 prepareBeverage() 方法是模板方法,它定义了制作饮料的算法框架。
  • brew()addCondiments() 是抽象方法,子类必须实现这些方法以提供具体的步骤。
  • customerWantsCondiments() 是一个钩子方法,子类可以选择覆盖它来改变算法的行为。
  • boilWater()pourInCup() 是具体方法,它们在父类中实现,子类可以直接使用。

通过这种方式,模板方法模式允许我们在不改变算法结构的情况下,灵活地改变算法的某些步骤。

总结

模板方法是一种高层定义骨架,底层实现细节的设计模式,适用于流程固定,但某些步骤不确定或可替换的情况。