设计模式专题(五)模板方法模式

目录

模板方法模式的定义

模板方法模式的应用场景

模板方法模式实现举例

模板方法模式的定义

定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

模板方法模式的通用类图如下:

设计模式专题(五)模板方法模式_第1张图片

 

模板方法模式确实非常简单,仅仅使用了Java的继承机制,但它是一个应用非常广泛的模式。其中,AbstractClass叫做抽象模板,它的方法分为两类:

基本方法:

基本方法也叫作基本操作,是由子类实现的方法,并且在模板方法被调用。

模板方法:

可以是一个或多个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑。

模板方法模式的应用场景

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

模板方法模式实现举例

如果你有一个任务,在一个星期内制造10万悍马车模型,只考虑最基本的实现,不考虑太多别的问题,你会怎么做?

既然不考虑扩展性,那就好办了,先按照最一般的经验设计类图,如下图所示

设计模式专题(五)模板方法模式_第2张图片

 

非常简单的实现,悍马车有两个型号,H1和H2。按照要求,只需要悍马模型,那就只给悍马模型,先写个抽象类,然后两个不同型号的实现类,通过简单的继承就可以实现业务要求。悍马模型的抽象类代码如下:

//悍马模型抽象类
public abstract class HummerModel{
    //模型发动
    protected abstract void start();
    //模型能停止
    protected abstract void stop();
    //模型喇叭会响
    protected abstract void alarm();
    //引擎会响
    protected abstract void engineBoom();
    //模型会跑
    protected abstract void run();
}

在抽象类中,我们定义了悍马模型必须具有的特性,能发动、停止、喇叭会响,引擎可以轰鸣,而且还可以停止。但是每个型号的悍马实现是不同的,H1型号悍马实现如下:

public class Hummer1Model extends HummerModel {
    @Override
    protected void start() {
        System.out.println("悍马H1发动......");
    }
    @Override
    protected void stop() {
        System.out.println("悍马H1停止......");
    }
    @Override
    protected void alarm() {
        System.out.println("悍马H1鸣笛......");
    }
    @Override
    protected void engineBoom() {
        System.out.println("悍马H1引擎声音是这样的......");
    }
    @Override
    protected void run() {
        //先发动汽车
        this.start();
        //引擎开始轰鸣
        this.engineBoom();
        //跑的过程中遇到一条狗,于是按喇叭
        this.alarm();
        //到达目的地停车
        this.stop();
    }
}

注意看run()方法,这是一个汇总方法,一个模型生产成功了,总要拿给客户检测,run()方法就是一种检验方法,让它跑起来,通过run()方法,把所有功能都测试到了。

H2型号悍马代码如下:

public class Hummer2Model extends HumanModel {
    @Override
    protected void start() {
        System.out.println("悍马H2发动......");
    }
    @Override
    protected void stop() {
        System.out.println("悍马H2停止......");
    }
    @Override
    protected void alarm() {
        System.out.println("悍马H2鸣笛......");
    }
    @Override
    protected void engineBoom() {
        System.out.println("悍马H2引擎声音是这样的......");
    }
    @Override
    protected void run() {
        //先发动汽车
        this.start();
        //引擎开始轰鸣
        this.engineBoom();
        //跑的过程中遇到一条狗,于是按喇叭
        this.alarm();
        //到达目的地停车
        this.stop();
    }
}

程序写到这里,就发现问题了,两个实现类的run()方法都是完全相同的,那这个run()方法的实现应该出现在抽象类,而不是实现类上,抽象是所有子类的共性封装。

注意:在软件开发过程中,如果相同的一段代码复制过两次,就需要对设计产生怀疑,架构师要明确说明为什么相同的逻辑要出现两次或者更多次。

既然发现问题了,那就需要马上改正,修改后的类图如下:

设计模式专题(五)模板方法模式_第3张图片

 

在改正后,在HumerModel中加入了一个run()方法,这个方法是一个实现方法,HumerModel修改后源代码如下:

//悍马模型抽象类
public abstract class HumanModel{
    //模型发动
    protected abstract void start();
    //模型能停止
    protected abstract void stop();
    //模型喇叭会响
    protected abstract void alarm();
    //引擎会响
    protected abstract void engineBoom();
    //模型会跑
    public final void run(){
        //先发动汽车
        this.start();
        //引擎开始轰鸣
        this.engineBoom();
        //跑的过程中遇到一条狗,于是按喇叭
        this.alarm();
        //到达目的地停车
        this.stop();
    }
}

在抽象的悍马模型上已经定义了run()方法的执行规则,先启动,然后引擎轰鸣,中间还要按一下喇叭,然后停车,他的两个具体实现类就不需要实现run()方法了。

场景类实现的任务就是把生产出的模型展现给客户,其源代码如下:

//场景类
public class Client{
    public static void main(String[] args){
        //需要H1型号的悍马
        HummerModel h1 = new Hummer1Model();
        //h1模型展示
        h1.run();
    }
}

运行结果如下:

悍马H1发动...
悍马H1引擎声音是这样的...
悍马H1鸣笛...
悍马H1停车...

你可能感兴趣的:(Java架构)