目录
一、模板方法模式
模板方法模式(Template Method Pattern)是一种行为设计模式,它在一个方法中定义了一个算法的骨架,而将一些步骤的实现延迟到子类中。
通过这种方式,模板方法模式可以将步骤的执行顺序控制在父类中,同时允许子类覆盖特定步骤的实现以满足具体需要。
1、结构
模板方法模式包含以下主要角色:
抽象类(Abstract Class)
定义抽象的基本操作,子类将重定义它们以实现算法的特定步骤
实现一个模板方法,定义算法的骨架
具体类(Concrete Class)
实现基本操作以完成算法中与特定子类相关的步骤
2、特性
固定算法结构:模板方法通过定义算法的骨架,确保算法的固定执行顺序。
可扩展步骤:子类可以覆盖父类中定义的抽象方法,从而扩展或修改某些步骤,而不影响整体算法的结构。
不可变模板方法:模板方法通常使用 final 修饰,这样子类就不能重写这个方法,从而保证了算法骨架的稳定性。
3、优缺点
3.1、优点
代码复用:通过在抽象类中定义公用的算法结构,可以减少代码重复,提高代码复用性。
灵活性和可扩展性:子类可以根据具体需求覆盖抽象方法,从而实现不同的具体行为,这提高了系统的灵活性和可扩展性。
控制反转:模板方法模式实现了一种变相的控制反转,由父类调用子类实现的具体方法,减少了子类对父类的依赖。
3.2、缺点
过度设计:如果算法步骤很简单或变化不大,使用模板方法模式可能导致过度设计,引入不必要的复杂性。
实现不直观:模板方法模式涉及继承和多态,对某些人来说可能不是特别直观,需要详细文档说明才能正确理解和使用。
4、使用场景
一次性实现算法的不变部分,将可变部分留给子类实现
各子类中公共的行为应被提取出来集中到公共父类中
控制子类扩展,只允许在特定点进行扩展
5、实现示例
5.1、抽象类
/**
* 抽象类 - 饮料制作模板
* 定义了制作饮料的算法骨架
*/
public abstract class BeverageTemplate {
// 模板方法 - 定义制作饮料的步骤(算法骨架)
public final void prepareBeverage() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
// 具体方法 - 烧水(所有饮料都一样)
private void boilWater() {
System.out.println("烧开水");
}
// 具体方法 - 倒入杯子(所有饮料都一样)
private void pourInCup() {
System.out.println("将饮料倒入杯子");
}
// 抽象方法 - 冲泡(由子类实现)
protected abstract void brew();
// 抽象方法 - 添加调料(由子类实现)
protected abstract void addCondiments();
// 钩子方法 - 顾客是否要加调料(默认返回true,子类可覆盖)
protected boolean customerWantsCondiments() {
return true;
}
}
5.2、实现类
具体子类 - 咖啡
/**
* 具体子类 - 咖啡
*/
public class Coffee extends BeverageTemplate {
@Override
protected void brew() {
System.out.println("冲泡咖啡粉");
}
@Override
protected void addCondiments() {
System.out.println("加入糖和牛奶");
}
// 覆盖钩子方法 - 询问用户是否要加调料
@Override
protected boolean customerWantsCondiments() {
String answer = getUserInput();
return answer.toLowerCase().startsWith("y");
}
}
具体子类 - 茶
/**
* 具体子类 - 茶
*/
public class Tea extends BeverageTemplate {
@Override
protected void brew() {
System.out.println("浸泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("加入柠檬");
}
// 覆盖钩子方法 - 茶默认不加调料
@Override
protected boolean customerWantsCondiments() {
return false;
}
}
5.3、测试类
public class BeverageTest {
public static void main(String[] args) {
System.out.println("======= 制作咖啡 =======");
BeverageTemplate coffee = new Coffee();
coffee.prepareBeverage();
System.out.println("\n======= 制作茶 =======");
BeverageTemplate tea = new Tea();
tea.prepareBeverage();
}
}
结果:
======= 制作咖啡 =======
烧开水
冲泡咖啡粉
将饮料倒入杯子
您的咖啡要加糖和牛奶吗 (y/n)? y
加入糖和牛奶
======= 制作茶 =======
烧开水
浸泡茶叶
将饮料倒入杯子