用多人运动给面试官解释模板方法模式,他表示我的想法很骚

说在前面:如果想最快速度温习这一设计模式,可直接跳到第4点的总结,不过其余3点个人觉得也非常有意思的!感兴趣的童鞋可以看看┗|`O′|┛ 嗷~~

模板方法模式是一个比较实用且简单的设计模式,它的关键点有:

(1)父类提供好方法模板,交给子类去实现

(2)父类定义好方法的执行顺序,对外暴露出一个执行方法,让子类调用执行。

1. 什么是模板方法模式

举一个贴近生活的例子:我们每个人的早上、下午、晚上都可以做不同的事:

(1)男程序员:早上敲代码、下午摸鱼、晚上多人运动

(2)女程序员:早上敲代码、下午Shopping、晚上看剧吃沙拉美容

(3)···

我们可以发现,不同的人有不同的行为,而每个人的行为都是有相同的执行顺序的(早上、下午、晚上)

image.png

我们回顾上面的两位成员,用代码表示是这样的:

public class GeGe {
    public void morning() {
        System.out.println("男程序员在敲代码");
    }
    public void afternoon() {
        System.out.println("男程序员在摸鱼");
    }
    public void evening() {
        System.out.println("男程序员在多人运动");
    }
    public void start() {
        morning();
        afternoon();
        evening();
    }
}
public class MeiMei {
    public void morning() {
        System.out.println("女程序员在敲代码");
    }
    public void afternoon() {
        System.out.println("女程序员在Shopping");
    }
    public void evening() {
        System.out.println("女程序员在看剧吃沙拉和护肤,美美哒");
    }
    public void start() {
        morning();
        afternoon();
        evening();
    }
}

如果还有一个DiDi(弟弟)类,他也要过每一天的生活,那样在程序里还要重新手写这几个方法,再实现它的逻辑,太龊了,一点都不程序员,所以我们很快可以想到:把相同的方法抽取出来,聚合到一个抽象类Human当中,让GeGe和MeiMei去继承这个抽象类,实现抽象方法,这样就优雅多了吧

public abstract class Human {
    protected abstract void morning();
    protected abstract void afternoon();
    protected abstract void evening();
    
    protected void start() {
        morning();
        afternoon();
        evening();
    }
}

到这里,你会看到 Human 就像一个模板类一样,提供好了三个方法让子类去重写,并且提供了调用方法。GeGe类就变成这样了:

public class GeGe extends Human {
    @Override
    public void morning() {
        System.out.println("男程序员在敲代码");
    }
    @Override
    public void afternoon() {
        System.out.println("男程序员在摸鱼");
    }
    @Override
    public void evening() {
        System.out.println("男程序员在多人运动");
    }
    
    public static void main(String[] args) {
        Human gege = new GeGe();
        gege.start();
    }
}
// 男程序员在敲代码
// 男程序员在摸鱼
// 男程序员在多人运动

同理,MeiMei 类就不贴出来了。这样的好处是:

(1)Human(人类)类已经提供好需要实现的方法,GeGe(哥哥)不需要去思考自己需要写哪些方法,直接重写父类要求的方法即可。

(2)由于在父类中已经提供了方法,里面定义好每个方法的执行顺序,子类按照父类给定的调用顺序去编写逻辑即可。

image.png

2. 使用 final 关键字

我们来回顾一下 Human 这一段代码

public abstract class Human {
    protected abstract void morning();
    protected abstract void afternoon();
    protected abstract void evening();
    
    protected void start() {
        morning();
        afternoon();
        evening();
    }
}

上面这段代码已经可以称为一个“合格”的模板方法模式了,但是还差一步,那就是标题中的“final”关键字。

final 关键字有以下作用:

(1)使一个方法永远无法被重写(重要!)

(2)使一个变量的值永远不能发生改变(引用变量则代表引用地址的值

(3)还有其它作用,但不是这篇博客的重点,可以参考 final关键字的所有作用

在模板方法模式下,子类不能破坏父类的调用顺序,所以为了保证这一点,我们需要在方法上加上 final 关键字。

public final void start() {
    morning();
    afternoon();
    evening();
}

到这里为止,我对模板方法模式的关键点做了小小的总结:

(1)模板方法模式是一个由父类提供好抽象方法以及调用顺序、由子类实现具体逻辑的设计模式

(2)使用 final 关键字的作用是确保子类无法破坏父类定义好的调用顺序,否则违背了该模式的定义(可以对final关键字的作用展开哦)

3. 扩展使用:钩子方法

钩子方法,第一次听到这个名字的时候,我的表情是这样的,为什么叫钩子,钩啥玩意儿?

后来搜了一下它的定义,简单理解,钩子方法:管理着某个方法,决定该方法是否执行的一个管理者

文字较为晦涩,我们直接来看下面这段代码:

public abstract class Human {
    protected abstract void morning();
    protected abstract void afternoon();
    protected abstract void evening();
    
    protected void start() {
        if (doSthOnMorning()) {
            morning(); 
        }
        afternoon();
        evening();
    }
    protected boolean doSthOnMorning() {
        return false;
    }
}

上面这段代码中的 doSthOnMorning 方法就是钩子方法:它决定了 morning 方法是否执行。如代码所示:如果早上没事做,就不需要调用 morning() 方法去告诉别人自己早上做了什么了。

我们可以这样理解钩子方法:它就是一个业务方法的开关按钮。

  • 如果按钮打开(true),那么业务方法就会被执行
  • 否则按钮关闭(false),业务方法不会被执行

4. 模板方法模式总结

  • 父类的作用

(1)父类总结好一套抽象方法(算法)模板,并对外暴露出一个通用的、不可被重写的执行方法,其内部定义好模板的调用顺序,让子类去调用。

(2)父类提供好每个算法模板的钩子(hook)方法,让子类自行决定是否要执行对应的方法

  • 子类的作用

(1)子类实现父类提供的抽象方法模板和钩子函数,自行实现每个抽象方法模板的逻辑

(2)子类通过操控钩子函数决定是否执行子类中实现好的方法模板

  • 可以围绕 final 关键字进行知识点的拓展进行讲解,所有面试官都喜欢主动的面试者!

image.png

关于模板方法设计模式到这里就结束了,它并不复杂,但是解释清楚父类和子类各自的作用,可以让面试官对你清晰的思路点赞!

各位小伙伴转载、收藏、点赞、评论,让我们一起进步!

作者:大众程序猿

座右铭:比我们优秀的人多了去,但这并不防止我们追梦!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值