最近在看《设计模式之禅》,为了能够更加深入的理解设计模式,达到学以致用。
这边记录一下自己的一些感受和看法,并结合具体代码实战来进行说明。
但凡和设计模式挂上钩,我们总是会觉得「高不可攀」。
然而实际上,设计模式是基于大量实际代码的经验总结,它来自于实际的代码。
与其说「高不可攀」,其实它反而是比较「接地气」。
而模板方法模式相信你看完本篇文章之后,会发现,原来这就是模板方法模式,然后就去看你之前的代码了。
理解设计模式最好的方法就是通过项目开发中的实际场景来说明。
大家做 Android 开发的时候写 Activity 应该都会看到下面类似代码吧?
private void getIntents() { // 从 Intent 获取传递过来的一些参数,设置到属性中 } private void findViewById() { // 通过 findViewById 来初始化各个组件 } private void setViews() { // 给组件设置监听或者初始状态 }假设我每个界面都这样写,那么重复代码太多了,很没必要。
虽然每个方法具体的逻辑不一样,但是都有这些操作。
这个时候我们第一个想法就是继承,抽取出一个 BaseActivity。
然后将这些通用代码都放到了 BaseActivity 里面,子类再来覆写就可以了。
但是还有一个问题,那就是,我每次都需要写下面代码:
getIntents(); findViewById(); setViews();尤其是通用代码多的时候,有时候手误可能导致某些界面这三个方法调用顺序还不一样。
那怎么办呢?我们可以抽取出一个方法,这个方法代表了这三个方法统一的调用顺序,这样就不怕手误写错了。
而这个方法就是我们的模板方法。
这样我后面的 Activity 都可以继承这个 BaseActivity,然后只需要调用 init 方法即可。
至于不同的 Activity 的逻辑我再在三个方法里面各自实现即可。
一听到这个词,是不是觉得有点「高大上」,似乎很 NB?
然而,听完我后面的讲述,你内心估计
我们上面的方法里面,并不是所有的 Activity 都有其他 Activity 传递数据过来的,因此 getIntents 这个方法不一定所有子类都要调用。
这个时候我们可以提供一个钩子方法,改动部分代码如下:
可以看到,通过钩子方法,当我们默认需要获取数据时,什么都不用改动,如果我们不需要获取数据,只需要覆写我们的钩子方法 isGetIntents 并返回 false 即可。
好了,有了初步的印象之后,接下来就正式的加深了解吧。
定义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.
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
简单的说就是父类定义了一个模板方法,在这个模板方法里面有一些特定的步骤。具体的步骤实现留给子类去处理。
父类的模板方法保持了各个子类的共性,模板方法里面的步骤使得每个子类都有自己的个性。
通用代码实现父类:
public abstract class AbstractPatternClass { /** * 基本方法,模板方法里面调用 */ protected abstract void firstModule(); /** * 基本方法,模板方法里面调用 */ protected abstract void secondModule(); /** * 模板方法,多个基本方法组合 */ final public void templateMethod() { firstModule(); secondModule(); } }具体子类:
public class ConcreteClass extends AbstractPatternClass { @Override protected void firstModule() { // TODO 子类实现自己的逻辑 } @Override protected void secondModule() { // TODO 子类实现自己的逻辑 } }