Java 设计模式西游篇 - 第十回:模板方法定规矩 天条戒律不可违
·
诗曰:
流程框架已定好,细节实现各不同。
模板方法定规矩,天条戒律不可违。
📖 故事
话说师徒四人来到"天条戒律殿",此地规定取经流程,不可更改。
如来佛祖道:“唐僧,取经流程已定,你等只需按部就班!”
唐僧问:“佛祖,这流程可能更改?”
如来笑道:“框架已定,细节你们自己发挥!此乃模板方法模式!”
🐉 踩坑打怪:流程混乱之劫
第一劫:流程不统一
// 没有模板方法,每个神仙渡劫方式不同
public class Wukong {
public void duJie() {
System.out.println("悟空渡劫:");
// 1. 准备
System.out.println(" 1. 准备仙丹");
// 2. 渡劫
System.out.println(" 2. 硬抗天雷");
// 3. 庆祝
System.out.println(" 3. 吃桃子庆祝");
}
}
public class Bajie {
public void duJie() {
System.out.println("八戒渡劫:");
// 1. 准备
System.out.println(" 1. 准备美食");
// 2. 渡劫
System.out.println(" 2. 边吃边抗");
// 3. 庆祝
System.out.println(" 3. 继续吃");
}
}
public class ShaSeng {
public void duJie() {
System.out.println("沙僧渡劫:");
// 1. 准备
System.out.println(" 1. 准备行李");
// 2. 渡劫
System.out.println(" 2. 挑着担子抗");
// 3. 庆祝
System.out.println(" 3. 整理行李");
}
}
如来摇头: “你等渡劫流程不统一,成何体统!”
第二劫:流程重复
// 每个神仙都写一遍相似的流程
public class Wukong {
public void duJie() {
prepare();
endure();
celebrate();
}
private void prepare() { /* ... */ }
private void endure() { /* ... */ }
private void celebrate() { /* ... */ }
}
public class Bajie {
public void duJie() {
prepare(); // 重复代码
endure(); // 重复代码
celebrate(); // 重复代码
}
private void prepare() { /* ... */ }
private void endure() { /* ... */ }
private void celebrate() { /* ... */ }
}
悟空抱怨: “佛祖!这代码重复太多了!”
⚔️ 模板方法模式大法
第一步:定义抽象模板
// 抽象渡劫模板
public abstract class AbstractDuJie {
// 模板方法:定义流程框架(final 防止子类修改)
public final void duJie() {
System.out.println("=== 开始渡劫 ===");
// 1. 准备阶段
prepare();
// 2. 渡劫阶段
endureHeavenlyLightning();
// 3. 庆祝阶段
celebrate();
System.out.println("=== 渡劫成功 ===\n");
}
// 具体方法:所有子类都一样
protected void prepare() {
System.out.println(" 1. 准备阶段:沐浴更衣,斋戒三日");
}
// 抽象方法:子类必须实现
protected abstract void endureHeavenlyLightning();
// 钩子方法:子类可以选择性覆盖
protected void celebrate() {
System.out.println(" 3. 庆祝阶段:常规庆祝");
}
// 钩子方法:控制流程
protected boolean shouldBless() {
return true; // 默认需要祝福
}
}
第二步:实现具体模板
// 悟空渡劫
public class WukongDuJie extends AbstractDuJie {
@Override
protected void endureHeavenlyLightning() {
System.out.println(" 2. 悟空渡劫:硬抗天雷!💪");
System.out.println(" 金钟罩护体,毫发无损!");
}
@Override
protected void celebrate() {
System.out.println(" 3. 庆祝阶段:吃仙桃!🍑");
}
}
// 八戒渡劫
public class BajieDuJie extends AbstractDuJie {
@Override
protected void endureHeavenlyLightning() {
System.out.println(" 2. 八戒渡劫:边吃边抗!🍖");
System.out.println(" 吃饱了才有力气抗!");
}
@Override
protected void celebrate() {
System.out.println(" 3. 庆祝阶段:大吃一顿!🍗");
}
@Override
protected boolean shouldBless() {
return false; // 八戒不需要祝福
}
}
// 沙僧渡劫
public class ShaSengDuJie extends AbstractDuJie {
@Override
protected void endureHeavenlyLightning() {
System.out.println(" 2. 沙僧渡劫:挑着担子抗!📦");
System.out.println(" 担子当避雷针!");
}
@Override
protected void prepare() {
System.out.println(" 1. 准备阶段:整理行李,准备渡劫");
}
@Override
protected void celebrate() {
System.out.println(" 3. 庆祝阶段:整理战利品!");
}
}
// 唐僧渡劫
public class TangSengDuJie extends AbstractDuJie {
@Override
protected void endureHeavenlyLightning() {
System.out.println(" 2. 唐僧渡劫:念经抗雷!📿");
System.out.println(" 金刚经护体!");
}
@Override
protected void prepare() {
super.prepare(); // 调用父类默认准备
System.out.println(" 额外准备:带上锦襕袈裟");
}
@Override
protected void celebrate() {
System.out.println(" 3. 庆祝阶段:念经感谢佛祖!🙏");
}
}
第三步:实战演练
public class Main {
public static void main(String[] args) {
// 悟空渡劫
AbstractDuJie wukong = new WukongDuJie();
wukong.duJie();
// 八戒渡劫
AbstractDuJie bajie = new BajieDuJie();
bajie.duJie();
// 沙僧渡劫
AbstractDuJie shaSeng = new ShaSengDuJie();
shaSeng.duJie();
// 唐僧渡劫
AbstractDuJie tangSeng = new TangSengDuJie();
tangSeng.duJie();
}
}
输出:
=== 开始渡劫 ===
1. 准备阶段:沐浴更衣,斋戒三日
2. 悟空渡劫:硬抗天雷!💪
金钟罩护体,毫发无损!
3. 庆祝阶段:吃仙桃!🍑
=== 渡劫成功 ===
=== 开始渡劫 ===
1. 准备阶段:沐浴更衣,斋戒三日
2. 八戒渡劫:边吃边抗!🍖
吃饱了才有力气抗!
3. 庆祝阶段:大吃一顿!🍗
=== 渡劫成功 ===
=== 开始渡劫 ===
1. 准备阶段:整理行李,准备渡劫
2. 沙僧渡劫:挑着担子抗!📦
担子当避雷针!
3. 庆祝阶段:整理战利品!
=== 渡劫成功 ===
=== 开始渡劫 ===
1. 准备阶段:沐浴更衣,斋戒三日
额外准备:带上锦襕袈裟
2. 唐僧渡劫:念经抗雷!📿
金刚经护体!
3. 庆祝阶段:念经感谢佛祖!🙏
=== 渡劫成功 ===
模板方法模式的Hook(钩子)
// 带钩子的模板方法
public abstract class AbstractDuJieWithHook {
public final void duJie() {
prepare();
// 钩子:子类可以控制是否执行
if (shouldBless()) {
bless();
}
endureHeavenlyLightning();
celebrate();
}
protected void prepare() {
System.out.println(" 准备阶段");
}
// 钩子方法
protected boolean shouldBless() {
return true;
}
protected void bless() {
System.out.println(" 佛祖祝福");
}
protected abstract void endureHeavenlyLightning();
protected void celebrate() {
System.out.println(" 庆祝阶段");
}
}
🏆 战斗总结
如来佛祖道: “模板方法模式,框架已定,细节自填。此乃天条戒律!”
悟空领悟: “原来如此!流程框架不能改,但具体实现可以自由发挥!”
| 要点 | 说明 |
|---|---|
| 模板方法 | 定义流程框架(final 防止修改) |
| 抽象方法 | 子类必须实现 |
| 具体方法 | 所有子类共享 |
| 钩子方法 | 子类可以选择性覆盖 |
本章要点
| 要点 | 说明 |
|---|---|
| 核心思想 | 定义一个操作中的算法骨架,而将一些步骤延迟到子类中 |
| 适用场景 | 固定流程、复用代码、框架设计 |
| 优点 | 代码复用、控制扩展、符合开闭原则 |
| 缺点 | 流程固定、可能限制灵活性 |
更多推荐




所有评论(0)