行为型模式
- 模板方法模式(Template Method Pattern)
- 命令模式(Command Pattern)
- 迭代器模式(Iterator Pattern)
- 观察者模式(Observer Pattern)
- 中介者模式(Mediator Pattern)
- 备忘录模式(Memento Pattern)
- 解释器模式(Interpreter Pattern)
- 状态模式(State Pattern)
- 策略模式(Strategy Pattern)
- 职责链模式(Chain of Responsibility Pattern)
- 访问者模式(Visitor Pattern)
模板方法模式(Template Method Pattern) 是一种行为型设计模式,它定义了一个操作中的算法骨架,允许子类在不改变算法结构的情况下重定义该算法的某些步骤。通过这个模式,可以将不变的部分放在父类中,而将可变的部分留给子类去实现。模板方法模式通常涉及两个主要部分:抽象类和具体子类。
主要角色
-
抽象类(Abstract Class):
- 定义了算法的骨架,即模板方法。
- 其中包含一个或多个抽象方法,这些方法将在子类中实现。
- 还可以包含一些具体方法(即已实现的方法)。
-
具体类(Concrete Class):
- 子类继承抽象类并实现其中的抽象方法,以完成算法中变动的部分。
模板方法模式的工作流程
- 父类定义一个“模板方法”,这个方法通常是一个完整的算法步骤,并且在其中调用了一些抽象方法和具体方法。
- 子类重写这些抽象方法来实现自己特定的行为,而算法的整体结构和流程由父类来控制。
模板方法模式的优点
- 代码复用:父类实现的固定步骤可以在多个子类中复用,减少了代码的重复性。
- 易于扩展:通过继承父类并实现不同的步骤,子类可以非常容易地进行功能扩展。
- 控制反转:父类控制着算法的流程,子类只需要关注具体的步骤,符合“控制反转”的设计思想。
模板方法模式的缺点
- 类的数量增多:由于模板方法模式需要抽象类和多个具体类,有时会导致类的数量增多,增加维护成本。
- 过度继承:如果父类设计不当,可能会导致不必要的继承关系,增加类的复杂性。
示例:制作饮料的过程
假设我们有一个饮料的制作过程。不同的饮料(比如咖啡和茶)有不同的步骤,但它们都有一些共同的步骤,比如煮水、倒入杯子等。使用模板方法模式,可以将共同的步骤放在父类中,而将不同的步骤(如制作咖啡或茶的方式)留给子类去实现。
// 饮料准备的抽象类
public abstract class Beverage {// 模板方法,定义了制作饮料的过程public final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}// 共同步骤:煮水private void boilWater() {System.out.println("Boiling water");}// 共同步骤:倒入杯子private void pourInCup() {System.out.println("Pouring into cup");}// 抽象方法,子类需要实现的步骤:冲泡饮料protected abstract void brew();// 抽象方法,子类需要实现的步骤:添加调料protected abstract void addCondiments();
}// 具体子类:咖啡
public class Coffee extends Beverage {@Overrideprotected void brew() {System.out.println("Brewing coffee");}@Overrideprotected void addCondiments() {System.out.println("Adding sugar and milk");}
}// 具体子类:茶
public class Tea extends Beverage {@Overrideprotected void brew() {System.out.println("Steeping the tea");}@Overrideprotected void addCondiments() {System.out.println("Adding lemon");}
}public class TemplateMethodDemo {public static void main(String[] args) {// 创建咖啡和茶的实例Beverage coffee = new Coffee();Beverage tea = new Tea();System.out.println("Making coffee:");coffee.prepareRecipe(); // 输出咖啡制作过程System.out.println("\nMaking tea:");tea.prepareRecipe(); // 输出茶制作过程}
}
代码解析
-
抽象类
Beverage
:- 定义了一个
prepareRecipe()
方法,这是整个算法的模板方法,它规定了制作饮料的流程。 boilWater()
和pourInCup()
是固定步骤,已经在父类中实现。brew()
和addCondiments()
是抽象方法,留给子类去实现,具体取决于饮料的种类。
- 定义了一个
-
具体类
Coffee
和Tea
:Coffee
和Tea
类分别实现了brew()
和addCondiments()
方法,定义了具体的制作步骤。
-
客户端代码
TemplateMethodDemo
:- 在客户端中,分别创建了
Coffee
和Tea
的实例,调用prepareRecipe()
方法来制作咖啡和茶。 - 无论是制作咖啡还是制作茶,共同的步骤(如煮水、倒入杯子)都是由父类
Beverage
中的实现完成的,而每种饮料的具体制作方法由各自的子类来完成。
- 在客户端中,分别创建了
模板方法模式的应用场景
- 多个子类有相同的算法,但某些步骤不同的场景:比如不同的饮料、餐饮、制作流程等。
- 框架设计:许多框架(如Spring框架)会提供一个模板方法,允许用户自定义具体的步骤。
- 工作流管理:在复杂的工作流中,可以定义一些固定步骤和可变步骤,使用模板方法来管理整个工作流的执行。
总结
模板方法模式通过定义一个固定的算法骨架,并将一些具体步骤延迟到子类中实现,提供了代码复用的同时也保留了灵活的扩展性。它能够让不同的子类在不修改父类的情况下,提供不同的行为实现。