模板模式

2019/09/12 设计模式 共 1916 字,约 6 分钟

模板模式

记不清这是学习设计模式的第几天了,反正今天是要说的是模板模式。

定义

Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure. 定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

类图

图片来自百度

模板方法模式类图

角色结构

基本方法:基本方法也叫做基本操作,是由子类实现的方法,并且在模板方法被调用。 模板方法:可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑。

实例

我觉得《设计模式之禅》里面的例子非常直观,在这里就引用秦老师的代码。
开车的流程是这样的:上车插钥匙启动汽车,可以选择按按喇叭,最后到目的地了就熄火下车,这就是一个开车的模板。

  1. 创建车的抽象类,它有一个需要子类实现的基本方法,有一个通用的方法,还有一个钩子方法,可以决定是否调用didi()方法。
public abstract class Car {
    /**
     * 基本方法1
     * 启动的抽象方法
     */
    protected abstract void start();
    /**
     * 具体模板
     */
    private void stop() {
        System.out.println("熄火了...");
    }
    /**
     * 此方法是否调用由钩子方法决定
     */
    private final void didi() {
        System.out.println("DiDiDi,按喇叭...");
    }

    /**
     * 模板方法
     * 验收方法
     */
    public final void run() {
        // 车启动
        this.start();
        // 若钩子方法为true,则按下喇叭
        if (isStart()) {
            this.didi();
        }
        // 车熄火
        this.stop();
    }
    /**
     * 钩子方法
     * 模板方法根据其返回值决定是否要响喇叭,子类可以覆写该返回值
     * @return
     */
    protected boolean isStart(){
        return true;
    }
}
  1. 创建两个子类,Benz类覆盖钩子方法
public class Hummer extends Car {
    /**
     * 启动的抽象方法
     */
    @Override
    protected void start() {
        System.out.println("Hummer...start...");
    }
}

public class Benz extends Car {
    /**
     * 启动的抽象方法
     */
    @Override
    protected void start() {
        System.out.println("Benz...start...");
    }
    /**
     * 钩子方法
     * 模板方法根据其返回值决定是否要响喇叭,子类可以覆写该返回值
     *
     * @return
     */
    @Override
    protected boolean isStart() {
        return false;
    }
}

  1. 创建测试类
public class Client {
    public static void main(String[] args) {
        ModelHummer hummer = new ModelHummer();
        hummer.run();

        ModelBenz benz = new ModelBenz();
        benz.run();
    }
}
  • 测试结果为
Hummer...start...
Hummer...stop...
template.ModelBenz不需要启动

模板方法模式的优缺点

优点

  1. 封装不变部分,扩展可变部分
    • 把认为是不变部分的算法封装到父类实现,而可变部分的则可以通过继承来继续扩展。
  2. 提取公共部分代码,便于维护
  3. 行为由父类控制,子类实现
    • 基本方法是由子类实现的,因此子类可以通过扩展的方式增加相应的功能,符合开闭原则。

缺点

  1. 按照我们的设计习惯,抽象类负责声明最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法。但是模板方法模式却颠倒了,抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂的项目中,会带来代码阅读的难度,而且也会让新手产生不适感。

使用场景

  1. 多个子类有公有的方法,并且逻辑基本相同时。
  2. 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
  3. 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为

源代码

GitHub地址

版权声明:本文为Planeswalker23所创,转载请带上原文链接,感谢。

文档信息

Search

    Table of Contents