欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式——模版方法

程序员文章站 2022-07-14 09:06:33
...

模版方法

定义:
在一个方法中定义一个算法的骨架,将一些步骤延迟到子类中。
模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤

举个栗子:某客户要生产一批不同型号的悍马模型

首先得抽象出一个悍马模型类

//悍马模型
public abstract class HummberModel {
   //能够发动   
    abstract void start();
   //能够刹车
    abstract void stop();
   //能滴滴
    abstract void alarm();
   //能跑
    void run();
}
//h1型号悍马
public class HummberH1Model extends HummberModel {
    @Override
    public void start() {
        System.out.println("H1开始发动");
    }
    @Override
    public void stop() {
        System.out.println("H1开始停止");
    }
    @Override
    public void alarm() {
      System.out.println("H1滴~滴滴~~");
    }
    @Override
    public void run(){
            this.start();//开始启动。
            this.alarm();//遇到一条狗,开始鸣笛
            this.stop();//到达目的地,停车
    };
}
//h2型号悍马
public class HummberH2Model extends HummberModel {
    @Override
    public void start() {
        System.out.println("H2开始发动");
    }
    @Override
    public void stop() {
        System.out.println("H2开始停止");
    }
    @Override
    public void alarm() {
      System.out.println("H2滴~滴滴~~");
    }
    @Override
    public void run(){
            this.start();//开始启动。
            this.alarm();//遇到一条狗,开始鸣笛
            this.stop();//到达目的地,停车
    };
}

由上面一些代码可以看出,H1与H2中的run()方法是一模一样的。那么这个run方法应该出现在抽象类,而不是实现类中。抽象类封装了子类的共性。因此对之前的代码进行修改。

  1. 将run()方法在抽象类中进行实现,并删除子类中的实现
public abstract class HummberModel {
   //能够发动   
    abstract void start();
   //能够刹车
    abstract void stop();
   //能滴滴
    abstract void alarm();
   //能跑
    final void run(){
            this.start();//开始启动。
            this.alarm();//遇到一条狗,开始鸣笛
            this.stop();//到达目的地,停车
    };
}
//h1模型
public class HummberH1Model extends HummberModel {
    @Override
    public void start() {
        System.out.println("H1开始发动");
    }
    @Override
    public void stop() {
        System.out.println("H1开始停止");
    }
    @Override
    public void alarm() {
      System.out.println("H1滴~滴滴~~");
    }
}

h2与h1类似,此处不多做赘述。
然后进行测试…..

 public static void main(String[] args) {
    HummberH1Model h1=new HummberH1Model();
     h1.run();
 }

测试结果:
H1开始发动
H1滴~滴滴~~
H1开始停止
OK!这就是传说中的模版方法了。是不是感觉特简单0.0。不过需要注意的是,为了防止恶意操作,模版方法一般都需要加final关键字修饰。

模版组成

抽象模版(HummberModel)中的方法分为基本方法和模版方法。
基本方法:由子类实现的方法,可以在模版方法中进行调用
模版方法: 由一个或多个基本方法组成的方法

优点

  1. 封装不变部分(模版方法),扩展可变部分(基本方法)
  2. 提取公共部分代码,便于维护
  3. 父类控制行为,子类控制具体实现

缺点

  1. 提高了代码阅读的难度

扩展

此时,需求发生了变化。因为每次启动车子时都会鸣笛,现在的需求是H1模型是人为控制鸣笛。H2模型是不让鸣笛。于是需要添加一个钩子方法如下

public abstract class HummberModel {
   .....(省略了其他基本方法)
   //能跑
    final void run(){
            this.start();//开始启动。
            if(this.isAlarm()){
              this.alarm();//遇到一条狗,开始鸣笛 
            }
            this.stop();//到达目的地,停车
    };

    //增加一个钩子方法
    abstract boolean isAlarm();
}

H1需要人为控制鸣笛

public class HummberH1Model extends HummberModel {
    private boolean isAlarm;

    .....(省略了其他基本方法)
    //由客户决定是否鸣笛
    public void setAlarm(boolean alarm){
        this.isAlarm=alarm;
    }
    //重写钩子方法
    @Override
    boolean isAlarm() {
        return this.isAlarm;
    }

}

H2不能鸣笛

public class HummberH2Model extends HummberModel {
    .....(省略了其他基本方法)
    //实现钩子方法
    @Override
    boolean isAlarm() {
        return false;
    }
}

进行测试

  public static void main(String[] args) {
    //H1模型  
    HummberH1Model h1=new HummberH1Model();
    h1.setAlarm(true);//客户决定鸣笛
    h1.run();
    //H2模型
    HummberH2Model h2=new HummberH2Model();
    h2.run();
}

钩子方法可以让子类影响到父类模版方法的调用。
当算法的某个实现可选的时候,可以使用钩子。
当算法的某个实现是必须的时候,使用抽象方法

模版方法模式就是在模版方法中按照一定的规则和顺序调用基本方法。