诗曰:

流程框架已定好,细节实现各不同。
模板方法定规矩,天条戒律不可违。

📖 故事

话说师徒四人来到"天条戒律殿",此地规定取经流程,不可更改。

如来佛祖道:“唐僧,取经流程已定,你等只需按部就班!”

唐僧问:“佛祖,这流程可能更改?”

如来笑道:“框架已定,细节你们自己发挥!此乃模板方法模式!”

🐉 踩坑打怪:流程混乱之劫

第一劫:流程不统一
// 没有模板方法,每个神仙渡劫方式不同
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 防止修改)
抽象方法 子类必须实现
具体方法 所有子类共享
钩子方法 子类可以选择性覆盖

本章要点

要点 说明
核心思想 定义一个操作中的算法骨架,而将一些步骤延迟到子类中
适用场景 固定流程、复用代码、框架设计
优点 代码复用、控制扩展、符合开闭原则
缺点 流程固定、可能限制灵活性

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐