1. 设计模式-模板方法模式介绍

模板方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个操作中的算法骨架,而将某些步骤延迟到子类中实现。模板方法使得子类可以重定义一个算法的某些特定步骤,而不改变算法的结构。这种模式非常适合处理那些存在固定步骤但某些步骤的具体实现可变的情况。

下面通过一个简单的例子来展示模板方法模式的应用:假设我们有一个冲泡饮料的基本流程,但具体每种饮料的准备过程(如加糖、加奶等)可能不同。

2. 使用步骤

首先,我们定义一个抽象的Beverage类,它包含一个模板方法prepareRecipe(),定义了冲泡饮料的基本步骤,并声明了一些抽象方法供子类实现。

public abstract class Beverage {
    // 模板方法,定义冲泡流程
    public final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

    // 具体步骤由子类实现
    protected abstract void brew();

    protected abstract void addCondiments();

    // 非抽象的基本步骤
    private void boilWater() {
        System.out.println("Boiling water");
    }

    private void pourInCup() {
        System.out.println("Pouring into cup");
    }

    // 可能需要子类覆盖的方法
    protected boolean customerWantsCondiments() {
        return true;
    }
}

然后,我们创建两个具体的饮料类CoffeeTea,它们继承自Beverage类并实现其中的抽象方法。

public class Coffee extends Beverage {
    @Override
    protected void brew() {
        System.out.println("Brewing coffee");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding sugar and milk to coffee");
    }
}

public class Tea extends Beverage {
    @Override
    protected void brew() {
        System.out.println("Steeping the tea");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding lemon");
    }

    // 覆盖父类方法,茶可能不需要默认的调料
    @Override
    protected boolean customerWantsCondiments() {
        return false;
    }
}

最后,我们可以通过客户端代码来演示如何使用这些类:

public class StarBuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new Coffee();
        beverage.prepareRecipe();
        System.out.println("");

        beverage = new Tea();
        beverage.prepareRecipe();
    }
}

3. 优点

  1. 代码复用:通过在父类中定义通用的操作流程,避免了重复代码。
  2. 灵活性:子类可以覆盖或实现特定的方法,使得算法的某些部分能够灵活变化。
  3. 扩展性:容易添加新的具体子类,只需实现模板中定义的抽象方法即可。

4. 缺点

  1. 过度抽象:如果模板方法中的抽象步骤过多,可能会导致子类实现过于复杂。
  2. 违背单一职责原则:父类可能需要知道一些本应属于子类的细节,以便定义模板方法。
  3. 难以理解:模板方法模式引入的抽象和钩子方法可能会使代码结构对初学者不够直观。

通过上述介绍和示例,我们可以看到模板方法模式在处理具有固定流程但部分步骤可变的场景下非常有效,但也需注意其潜在的设计陷阱。