博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模板方法模式.
阅读量:5117 次
发布时间:2019-06-13

本文共 2997 字,大约阅读时间需要 9 分钟。

一、概念

  • 模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
  • 解析:模板方法模式用来创建一个算法的模板。什么是模板?模板就是一个方法。更具体地说,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以确保算法的结构保持不变,同时由子类提供部分实现。
  • 角色:
     1、抽象模板(Abstract Template):定义模板方法,规范了一组步骤,其中父类可以实现其中的某些步骤,需要由子类实现的步骤声明为 abstract。
     2、具体模板(Concrete Template):继承抽象父类,实现抽象父类中声明为 abstract 的方法。

avatar

二、Demo 实现

我们打算定义一个咖啡因饮料冲泡流程,把流程中相同的步骤放在一起,同时,不同的饮料还能有自己的具体实现。

1、抽象模板

public abstract class CaffeineBeverage {    /**     * @Description      * 1、模板方法,定义算法的步骤。     * 2、我们一般把模板方法定义成 final,不希望子类覆盖。     */    public final void prepareRecipe() {        //1、把水煮沸        boilWater();        //2、用热水泡饮料(具体什么饮料未知)        brew();        //3、把饮料倒进杯子        pourIncup();        //4、往饮料中添加调料(具体什么调料未知)        if (wantAddCondiments()) {            addCondiments();        }    }    /**     * @Description 需要子类提供实现的步骤定义为抽象     */    protected abstract void brew();    protected abstract void addCondiments();    /**     * @Description 由父类提供实现,又不希望被子类重写的,封装成 private。     */    private void boilWater() {        System.out.println("Boiling water");    }    private void pourIncup() {        System.out.println("Pouring into cup");    }    /**     * @Description 钩子方法     * 1、钩子是一种被声明在抽象类中的方法,当只有空的或者默认的实现。     * 2、钩子的存在,可以让子类有能力对算法的不同点进行挂钩(重写)。     * 3、要不要挂钩(重写),由子类自己决定。     */    protected boolean wantAddCondiments() {        return true;    }}

这里,我们定义了一个抽象模板,规范了具体的冲泡流程 —— 把水煮沸->泡饮料->倒杯子->添加调料。在抽象模板中,我们有三种类型的方法,一种需要子类提供实现的,我们定义为 abstract ;一种父类提供实现,又不希望被子类覆盖的,我们定义为 private;还有一种称为钩子方法,父类提供默认实现,子类可自由选择是否重写父类的方法。

2、具体模板

public class Coffee extends CaffeineBeverage {    @Override    protected void brew() {        System.out.println("Dripping Coffee through filter");    }    @Override    protected void addCondiments() {        System.out.println("Adding Suger and Milk");    }}
public class Tea extends CaffeineBeverage {    @Override    protected void brew() {        System.out.println("Steeping the tea");    }    @Override    protected void addCondiments() {        System.out.println("Adding Lemon");    }    /**    * @Description 子类重写钩子方法    */    @Override    protected boolean wantAddCondiments() {        return false;    }}

具体模板继承了抽象模板,实现了抽象模板中定义为 abstract 的步骤方法,并可以自己选择是否重写钩子方法。

3、测试

public class Test {    public static void main(String[] args) {        CaffeineBeverage coffee = new Coffee();        CaffeineBeverage tea = new Tea();        coffee.prepareRecipe();        tea.prepareRecipe();    }}

avatar

三、总结

  • 模板方法模式的通用类图非常简单,仅仅使用了Java的继承机制,但它是一个非常广泛的模式。
  • 优点:
     1、封装不变部分,扩展可变部分。把认为不变部分的算法封装到父类中实现,而可变部分的则可以通过继承来继续扩展。可以将代码最大复用化。
     2、父类规范算法行为,子类提供完整实现。
  • 使用场景:
     1、多个子类有共有的方法,并且逻辑基本相同。
     2、一次性实现一个算法的不变部分,并且将可变的行为留给子类来完成。
  • 为防止子类改变模板方法中的算法,可以将模板方法声明为 final。
  • 策略模式和模板方法模式都封装算法,但是策略模式使用的是组合,模板方法模式使用的是继承。
  • 工厂方法是模板方法的一种特殊版本。
  • 模板方法导致一种反向的控制结构,这种结构有时被称为“好莱坞原则“。
  • 好莱坞原则:别调用我们,我们会调用你。在好莱坞原则之下,我们允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些低层组件。换句话说,高层组件对待低层组件的方式是“别调用我们,我们会调用你”。
  • 低层组件可以调用高层组件中的方法(实际上子类会常常调用其从父类中继承所来的方法),但是我们要做的是要避免让高层和底层组件之间有明显的环状依赖

转载于:https://www.cnblogs.com/jmcui/p/10153755.html

你可能感兴趣的文章
接口自动化之数据依赖
查看>>
自动化框架之pytest
查看>>
jmeter(1)添加header和cookie
查看>>
jmeter接口上传图片功能
查看>>
Hbuild在线云ios打包失败,提示BuildConfigure Failed 31013 App Store 图标 未找到 解决方法...
查看>>
Vue 利用指令实现禁止反复发送请求
查看>>
找到树中指定id的所有父节点
查看>>
编码艺术-代码架构的思考
查看>>
如何合理使用数据库锁
查看>>
使用Xcode的Targets来管理开发和生产版本的构建
查看>>
便捷编程-Xcode常用第三方插件 (随时更新)_Swift版本
查看>>
1.5 使用电脑测试MC20的发送英文短信功能
查看>>
线性递推阶乘的逆元
查看>>
C#访问数据库的步骤
查看>>
畅销移动应用开发的10个步骤(转载)
查看>>
发现的问题
查看>>
今天新开通了博客
查看>>
使用go, gin, gorm编写一个简单的curd的api接口
查看>>
完美解释if-modified-since/not-modified 文件头的意义
查看>>
Syscall param open(filename) points to unaddressable byte(s)
查看>>