设计模式之模板方法模式实战解析

本文微信公众号「AndroidTraveler」首发。

背景

最近在看《设计模式之禅》,为了能够更加深入的理解设计模式,达到学以致用。
这边记录一下自己的一些感受和看法,并结合具体代码实战来进行说明。

模板方法模式

但凡和设计模式挂上钩,我们总是会觉得「高不可攀」。
然而实际上,设计模式是基于大量实际代码的经验总结,它来自于实际的代码。
与其说「高不可攀」,其实它反而是比较「接地气」。
而模板方法模式相信你看完本篇文章之后,会发现,原来这就是模板方法模式,然后就去看你之前的代码了。

小例子初识模板方法模式

理解设计模式最好的方法就是通过项目开发中的实际场景来说明。

大家做 Android 开发的时候写 Activity 应该都会看到下面类似代码吧?

private void getIntents() {
    // 从 Intent 获取传递过来的一些参数,设置到属性中
}

private void findViewById() {
    // 通过 findViewById 来初始化各个组件
}

private void setViews() {
    // 给组件设置监听或者初始状态
}

假设我每个界面都这样写,那么重复代码太多了,很没必要。
虽然每个方法具体的逻辑不一样,但是都有这些操作。

这个时候我们第一个想法就是继承,抽取出一个 BaseActivity。
然后将这些通用代码都放到了 BaseActivity 里面,子类再来覆写就可以了。

但是还有一个问题,那就是,我每次都需要写下面代码:

getIntents();
findViewById();
setViews();

尤其是通用代码多的时候,有时候手误可能导致某些界面这三个方法调用顺序还不一样。
那怎么办呢?我们可以抽取出一个方法,这个方法代表了这三个方法统一的调用顺序,这样就不怕手误写错了。
而这个方法就是我们的模板方法

public abstract class BaseActivity extends Activity {
    /**
     * 从 Intent 获取传递过来的一些参数,设置到属性中
     */
    protected abstract void getIntents();

    /**
     * 通过 findViewById 来初始化各个组件
     */
    protected abstract void findViewById();

    /**
     * 给组件设置监听或者初始状态
     */
    protected abstract void setViews();

    /**
     * 模板方法
     */
    final public void init() {
        getIntents();
        findViewById();
        setViews();
    }
}

这样我后面的 Activity 都可以继承这个 BaseActivity,然后只需要调用 init 方法即可。
至于不同的 Activity 的逻辑我再在三个方法里面各自实现即可。

钩子方法

一听到这个词,是不是觉得有点「高大上」,似乎很 NB?
然而,听完我后面的讲述,你内心估计

我们上面的方法里面,并不是所有的 Activity 都有其他 Activity 传递数据过来的,因此 getIntents 这个方法不一定所有子类都要调用。
这个时候我们可以提供一个钩子方法,改动部分代码如下:

/**
 * 模板方法
 */
final public void init() {
    if (isGetIntents()) {
        getIntents();
    }
    findViewById();
    setViews();
}

/**
 * 钩子方法,是否需要设置数据,默认为 true
 * @return
 */
protected boolean isGetIntents() {
    return true;
}

可以看到,通过钩子方法,当我们默认需要获取数据时,什么都不用改动,如果我们不需要获取数据,只需要覆写我们的钩子方法 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 子类实现自己的逻辑
    }
}

场景使用类:

public class PatternTest {
    public static void main(String[] args) {
        AbstractPatternClass abstractPatternClass = new ConcreteClass();
        // 调用模板方法
        abstractPatternClass.templateMethod();
    }
}

钩子方法我们上面已经说过了,相信聪明的你知道如何使用,这里就不再赘述了。

注意点

父类中的基本方法尽量设计为 protected 类型,符合迪米特法则。
父类中的模板方法一般设置为 final,不允许子类覆写。这样的目的一个是为了避免子类恶意操作,一个是为了模板的共性。

应用

当你在写代码经常用到复制和粘贴快捷键时,你就要考虑是不是可以进行抽取。
当你修改一个地方的时候,发现其他地方也要连带修改,也需要考虑一下。
多个子类有公共方法,并且逻辑基本相同。
复杂的一些算法之类的,可以让子类通过基本方法传递一些参数,核心逻辑放在模板方法里面。
重构项目的时候,也可以考虑一下把相同代码抽取到父类,通过钩子方法定制化模板。

结语

最后一点就是注意不要滥用设计模式,不要为了设计而设计

参考资料
设计模式之禅(第2版)

原文地址:https://www.cnblogs.com/nesger/p/11444583.html

时间: 2024-11-05 18:28:28

设计模式之模板方法模式实战解析的相关文章

【大话设计模式】—— 模板方法模式

一.概念 上一篇文章刚刚讲了[大话设计模式]-- 原型模式,原型模式主要是通过Clone()方法,创建新的对象,免去了初始化的过程.模板方法模式也特别会"偷工减料",把不变的行为搬移到超类,去除子类中的重复代码,将代码的复用优势展现的淋漓尽致.它为我们提供了特定的结构和样式,我们只需关心填充数据内容就好,省心啊- 下面让我们来看一下它的准确定义: 模板方法(TemplateMethod)模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构

设计模式之模板方法模式(Template Method)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

【设计模式】——模板方法模式

模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定的步骤.当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法模式来处理. AbstractClas是抽象类,其实也就是一抽象模板,定义并实现了一个模板方法.这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现.顶级逻辑也有可能调用一些具体

大话设计模式_模板方法模式(Java代码)

模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 简单描述:多个类的行为是差不多的,只是某些局部不一样,则交由父类中抽象出这些子类中相同的部分,父类中定义出不同的部分的接口(方法),这些不同部分的方法则由子类去实现,通过多态,实现代码的重用 大话设计模式中的截图: 例子代码: AbstractClass类: 1 package com.longsheng.templatemethod; 2 3 public

【设计模式】模板方法模式

模板方法模式 一个父类[运动会]类 两个子类,一个[CClass1]类,一个[CClass2]类,班级类是运动会类的子类,父类制定了运动会的流程(算法的逻辑架构),子类分别去实现流程中的具体实现. 子类不需要重写流程,只需要重写流程中每一项的具体内容. 以此为例,流程就是先干什么.后干什么.再干什么,而每一项就是分别干的内容. /************************************************************************ 设计模式 模板方法模式

设计模式(8)--模板方法模式

关键词 :hook 钩子    Applet 中 init() destory() 为钩子,需要子类去实现. 新原则: 别调用我们,我们会调用你们    高层调用低层   低层不能调用高层. 目的 :封装算法 模板方法:子类决定如何实现算法中的步骤 策略:封装可互换的行为,然后使用委托来决定要采用哪一个行为 工厂方法:由子类决定实例化哪个具体类 OO原则:新原则上面 OO模式:模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类.模板方法使得子类可以在不改变算法的结构的情况下,重

设计模式之模板方法模式

(文章的部分内容参考了<设计模式之禅>一书,大家也可以读读看,内容写的非常好) 什么是模板方法模式 它的定义如下: 定义一个操作中的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 读起来很绕口,其实通俗的说就是父类里面定义一些抽象方法,自己不去实现,交由子类去具体实现,父类只负责管理这些抽象方法的运行顺序,管理运行顺序的方法就是模板方法. 举个具体的使用场景:我们画画一般都是先画线稿,然后再进行上色(不要和我说厚涂..),不过不同的画师的

Android 设计模式之模板方法模式

模板方法模式的定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 设计原则:别调用我们,我会调用你,(就好比猎头和求职者,求职者不需要去找猎头,猎头只要有工作就会找到你)称之为好莱坞原则 引用一个例子,一个店中有两饮料:咖啡和茶,他们的冲泡方法 第一步:都是要用沸水 第二步:用热水泡咖啡或茶 第三步:把饮料倒进杯子 第四步:在饮料中加入适当的调料 在上面的步骤中一.三是一样的,可以抽取出来放在基类中,二.四不一

14.设计模式_模板方法模式

一.引言 提到模板,大家肯定不免想到生活中的"简历模板"."论文模板"."Word中模版文件"等,在现实生活中,模板的概念就是--有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新它,例如简历模板,下载下来的简历模板的格式都是相同的,然而我们下载下来简历模板之后我们可以根据自己的情况填充不同的内容要完成属于自己的简历.在设计模式中,模板方法模式中模板和生活中模板概念非常类似,下面让我们就详细介绍模板方法的定义,大家可以根据生活中模板的概