我是靠谱客的博主 激动眼睛,最近开发中收集的这篇文章主要介绍Java设计模式之行为型-模板方法模式 (Template Method)附链定义场景示例总结参考,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

????文章示例代码????

附链

你也可以在这些平台阅读本文:

  • 语雀
  • 个人博客

定义

定义一个算法的步骤,并允许子类为一个或者多个步骤提供实现。

模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

场景示例

笔者这里以做番茄炒蛋为例。笔者将做番茄炒蛋的步骤分为以下几步:倒油、放鸡蛋、放番茄、倒调料、翻炒。不考虑多余的细节问题,不同的人做番茄炒蛋的步骤应该是类似的。

创建抽象模板

这里主要定义炒菜的步骤。

/**
 * @author zhh
 * @description 抽象模板类
 * @date 2020-02-27 15:47
 */
public abstract class AbstractCook {

    /**
     * 做饭的整体步骤
     */
    protected final void cook() {
        this.pourOil();
        this.addEgg();
        this.addTomato();
        this.pourSeasoning();
        this.stirFry();
        if (needChoppedGreenOnion()) {
            this.addChoppedGreenOnion();
        }
    }

    /**
     * 倒油
     */
    final void pourOil() {
        System.out.println("倒入食用油");
    }

    /**
     * 放鸡蛋
     */
    final void addEgg() {
        System.out.println("放入鸡蛋");
    }

    /**
     * 放番茄
     */
    final void addTomato() {
        System.out.println("放入番茄");
    }

    /**
     * 翻炒
     */
    final void stirFry() {
        System.out.println("快速翻炒");
    }

    /**
     * 放葱花
     */
    final void addChoppedGreenOnion() {
        System.out.println("放点葱花");
    }

    /**
     * 是否需要葱花 (钩子方法)
     */
    protected boolean needChoppedGreenOnion() {
        return false;
    }

    /**
     * 倒调味品
     */
    abstract void pourSeasoning();
}

这里的 needChoppedGreenOnion() 是一个钩子方法,让具体的子类来决定是否添加葱花,默认不添加。

以上的部分方法用 final 修饰,是为了防止子类对其进行重写。

创建具体子类

这里以笔者做饭和女朋友做饭为例。由于两人的口味不同,倒入的调味品会存在些许差异。而且笔者喜欢在番茄炒蛋中加入葱花。

/**
 * @author zhh
 * @description 具体子类
 * @date 2020-02-27 16:04
 */
public class MeCook extends AbstractCook {

    @Override
    void pourSeasoning() {
        System.out.println("放点盐");
        System.out.println("放点酱油");
    }

    /**
     * 此处覆盖了父类钩子方法的默认实现
     */
    @Override
    protected boolean needChoppedGreenOnion() {
        return true;
    }
}


/**
 * @author zhh
 * @description 具体子类
 * @date 2020-02-27 16:07
 */
public class GirlFriendCook extends AbstractCook {

    @Override
    void pourSeasoning() {
        System.out.println("放点盐");
    }
}

我们可以看到在 MeCook 类中重写了父类的 needChoppedGreenOnion() 方法,那么对于父类中模板方法执行 needChoppedGreenOnion() 方法时,拿到的其实是子类方法的返回值。

测试类及输出

/**
 * @author zhh
 * @description 测试类
 * @date 2020-02-27 16:13
 */
public class Test {

    public static void main(String[] args) {
        // 我做番茄炒蛋
        System.out.println("---我做番茄炒蛋 开始---");
        AbstractCook meCook = new MeCook();
        meCook.cook();
        System.out.println("---我做番茄炒蛋 结束---");

        // 女朋友做番茄炒蛋
        System.out.println("---女朋友做番茄炒蛋 开始---");
        AbstractCook girlFriendCook = new GirlFriendCook();
        girlFriendCook.cook();
        System.out.println("---女朋友做番茄炒蛋 结束---");
    }
}

测试类输出的结果如下:

—我做番茄炒蛋 开始—
倒入食用油
放入鸡蛋
放入番茄
放点盐
放点酱油
快速翻炒
放点葱花
—我做番茄炒蛋 结束—
—女朋友做番茄炒蛋 开始—
倒入食用油
放入鸡蛋
放入番茄
放点盐
快速翻炒
—女朋友做番茄炒蛋 结束—

类结构图

以上示例类的结构图如下所示

总结

适用场景

  • 算法的整体步骤固定,但其中的个别部分易变。
  • 多个子类存在公共的行为,可以将其提取出来并且集中到一个公共父类当中,避免代码重复。

优点

  • 父类提供公共部分代码,提高复用性。
  • 将不变部分的算法封装到父类中实现,把可变部分的算法由子类继承去实现,提高了扩展性。

缺点

  • 对于每个不同的实现都需要一个子类来实现,导致类数目的增加,增加系统实现的复杂度。
  • 父类中的抽象方法由自子类实现,如果父类添加新的抽象方法,所有的子类都需要修改。

扩展

钩子方法:提供缺省行为,子类可以在必要时进行扩展。

参考

  • 《Head First 设计模式》
  • 《大话设计模式》
  • 维基百科-模板方法
  • 菜鸟教程-模板模式

最后

以上就是激动眼睛为你收集整理的Java设计模式之行为型-模板方法模式 (Template Method)附链定义场景示例总结参考的全部内容,希望文章能够帮你解决Java设计模式之行为型-模板方法模式 (Template Method)附链定义场景示例总结参考所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部