揭秘模板方法模式的烹饪哲学——模板方法模式
如果在学习 Java 的过程中,对继承、重写这些关键知识点稍感生疏,记忆有些模糊不清了,不妨参考一下我的上一篇文章:【Java 的继承:方法;属性?】相信能为你答疑解惑,助你重拾清晰记忆。
开篇引趣
深夜的出租公寓里,小张对着滋滋作响的平底锅犯愁。他刚在社交平台刷到一条《做饭万能公式》,上面赫然写着:
「红烧公式」:焯水→爆香→调味→炖煮→收汁
「辣炒公式」:爆香小米辣→加火锅底料→炒菜→调味
这些看似简单的步骤组合,竟能变幻出宫保鸡丁、麻婆豆腐等百道菜肴。这让人不禁思考:为何固定的烹饪框架能衍生出无限风味? 这种「骨架统一,细节自由」的智慧,正是软件工程中模板方法模式(Template Method Pattern) 的精髓
当厨房变成代码战场(模板方法前)
假设我们要开发一个智能菜谱系统,传统程序员可能会写出这样的代码:
// 反例:重复的烹饪流程
class KungPaoChicken {
void cook() {
marinate(); // 腌制鸡肉
stirFryGarlic(); // 爆香蒜末
addChili(); // 加入辣椒
thickenSauce(); // 勾芡收汁
}
}
class MapoTofu {
void cook() {
boilTofu(); // 焯水豆腐
stirFryChiliBean();// 炒豆瓣酱
simmer(); // 小火慢炖
thickenSauce(); // 重复的勾芡步骤
}
}
这就像在厨房为每道菜单独配备锅铲和灶台——重复的勾芡、爆香步骤被机械复制,一旦需要调整火候控制逻辑,开发者不得不逐个修改几十个类
米其林主厨的代码秘籍(模板方法后)
模板方法模式如同一位算法主厨,它将烹饪分解为标准化操作手册:
- 固化骨架:在抽象父类定义
cook()
模板方法,确立「预处理→爆香→烹制→收尾」的不可变流程 - 开放细节:将「爆香方式」「调味手法」声明为抽象方法,允许子类自由创新
- 智能钩子:通过
needThickening()
等方法,支持「宫保鸡丁要勾芡,清炒时蔬免收汁」的个性化定制
abstract class AbstractCooking {
// 模板方法(final锁定流程)
public final void execute() {
prepareIngredients();
heatOil();
aromaBlasting(); // 抽象方法:爆香方式
mainCooking(); // 抽象方法:主料烹制
if(needThickening()) thicken(); // 钩子控制收汁
}
private void heatOil() {
System.out.println("热锅凉油至180℃");
}
protected abstract void aromaBlasting();
protected abstract void mainCooking();
// 钩子方法:默认需要收汁
protected boolean needThickening() {
return true;
}
}
// 具体实现:麻婆豆腐
class MapoTofu extends AbstractCooking {
@Override
protected void aromaBlasting() {
System.out.println("煸炒郫县豆瓣酱+花椒粒");
}
@Override
protected void mainCooking() {
System.out.println("嫩豆腐切块入红汤慢炖");
}
// 重写钩子:麻辣菜肴必须收汁
@Override
protected boolean needThickening() {
return true;
}
}
完整代码
抽象类
abstract class AbstractCooking {
// 模板方法(final锁定流程)
public final void execute() {
prepareIngredients();
heatOil();
aromaBlasting(); // 抽象方法:爆香方式
mainCooking(); // 抽象方法:主料烹制
if(needThickening()) thicken(); // 钩子控制收汁
}
private void prepareIngredients() {
System.out.println("准备食材以及配料");
}
private void heatOil() {
System.out.println("热锅凉油至180℃");
}
private void thicken() {
System.out.println("收汁");
}
// 钩子方法:默认需要收汁
protected boolean needThickening() {
return true;
}
protected abstract void aromaBlasting();
protected abstract void mainCooking();
}
子类:宫保鸡丁
/**
* 宫保鸡丁
*/
public class KungPaoChicken extends AbstractCooking {
@Override
protected void aromaBlasting() {
System.out.println("葱姜蒜爆香");
}
@Override
protected void mainCooking() {
System.out.println("胡萝卜、鸡肉、花生切丁爆炒");
}
@Override
protected boolean needThickening() { // 不需要收汁
return false;
}
}
子类:麻婆豆腐
/**
* 麻婆豆腐
*/
public class MapoTofu extends AbstractCooking {
@Override
protected void aromaBlasting() {
System.out.println("煸炒郫县豆瓣酱+花椒粒");
}
@Override
protected void mainCooking() {
System.out.println("嫩豆腐切块入红汤慢炖");
}
}
测试类:
public class TestMain {
public static void main(String[] args) {
System.out.println("【制作宫保鸡丁】");
AbstractCooking kungPaoChicken = new KungPaoChicken();
kungPaoChicken.execute();
System.out.println("-------------------------");
System.out.println("【制作麻婆豆腐】");
AbstractCooking mapoTofu = new MapoTofu();
mapoTofu.execute();
}
}
总结与升华
从烹饪到架构的思维跃迁,这种设计模式让代码如同模块化烹饪:
- 固定步骤:准备配料、热油
- 差异化步骤:爆香方式、主料烹制
- 特殊化:收汁
当我们在代码中注入这种「烹饪哲学」,重复劳动将升华为艺术创作。