设计模式-模板方法模式 – 记忆角落

设计模式-模板方法模式

/ 0评 / 0

介绍

模板方法是一种行为类设计模式。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

模板方法是一个定义在父类的方法(抽象类),具体实现由子类实现

优点:

1、封装不变部分,扩展可变部分。

2、提取公共代码,便于维护。

3、行为由父类控制,子类实现。

缺点:

每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

使用场景:

1、有多个子类共有的方法,且逻辑相同。

2、重要的、复杂的方法,可以考虑作为模板方法。

注意事项:

1.为防止恶意操作,一般模板方法都加上 final 关键词,不允许被重写

2.抽象模板中的基本方法尽量设计为protected类型,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected类型。实现类若非必要,尽量不要扩大父类中的访问权限

实现

模拟场景:

汽车都有以下步骤:启动汽车、停止汽车、响喇叭、汽车跑起来...等等

UML图:

image-20211021234031326

基础的汽车类

public abstract class Car {

    protected abstract void start();

    protected abstract void stop();

    protected abstract void alarm();

    final void run(){
        start();
        alarm();
        stop();
    }
}

宝马汽车:

public class BMWCar extends Car{

    @Override
    protected void start() {
        System.out.println("BMW发动……");

    }

    @Override
    protected void stop() {
        System.out.println("BMW停止……");
    }

    @Override
    protected void alarm() {
        System.out.println("BMW响喇叭……");
    }
}

奔驰汽车:

public class MercedesCar extends Car{

    @Override
    protected void start() {
        System.out.println("Mercedes发动……");
    }

    @Override
    protected void stop() {
        System.out.println("Mercedes停止……");
    }

    @Override
    protected void alarm() {
        System.out.println("Mercedes响喇叭……");
    }
}

测试运行:

    public static void main(String[] args) {

        Car bmw = new BMWCar();
        bmw.run();

        System.out.println("====================");

        Car mercedes = new MercedesCar();
        mercedes.run();

    }
-------------------
BMW发动……
BMW响喇叭……
BMW停止……
====================
Mercedes发动……
Mercedes响喇叭……
Mercedes停止……

拓展延申

首先不是所有的汽车都会在运行的时候响喇叭(市区禁鸣),那这个时候我们该咋办呢?

解决方案如下:

  修改 Car 添加一个是否能响喇叭的方法,让自身判断是否能响喇叭。同时子类需要增加相应的实现。

基础的汽车类

public abstract class Car {

    protected abstract void start();

    protected abstract void stop();

    protected abstract void alarm();

    protected abstract boolean isAlarm();

    final void run(){
        start();
        if(isAlarm()){
            alarm();
        }
        stop();
    }
}

宝马汽车:

public class BMWCar extends Car{

    @Override
    protected void start() {
        System.out.println("BMW发动……");

    }

    @Override
    protected void stop() {
        System.out.println("BMW停止……");
    }

    @Override
    protected void alarm() {
        System.out.println("BMW响喇叭……");
    }

    @Override
    protected boolean isAlarm() {
        System.out.println("我不经过市区可以响喇叭....");
        return true;
    }
}

奔驰汽车:

public class MercedesCar extends Car{

    @Override
    protected void start() {
        System.out.println("Mercedes发动……");
    }

    @Override
    protected void stop() {
        System.out.println("Mercedes停止……");
    }

    @Override
    protected void alarm() {
        System.out.println("Mercedes响喇叭……");
    }

    @Override
    protected boolean isAlarm() {
        System.out.println("我天天经过市区塞车...还不可以响喇叭....");
        return false;
    }
}

测试运行:

BMW发动……
我不经过市区可以响喇叭....
BMW响喇叭……
BMW停止……
====================
Mercedes发动……
我天天经过市区塞车...还不可以响喇叭....
Mercedes停止……

延申涉及的钩子方法

  在我们的Car抽象类中isAlarm()的返回值就是影响了模板方法的执行结果,该方法就叫做钩子方法(HookMethod)。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注