本文微信公众号「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 {@Overrideprotected void firstModule() {// TODO 子类实现自己的逻辑}@Overrideprotected 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

设计模式之模板方法模式实战解析相关推荐

  1. Carson带你学设计模式:模板方法模式(Template Method)

    前言 今天Carson来全面总结最常用的设计模式 - 模板方法模式. Carson带你学设计模式系列文章 Carson带你学设计模式:这是一份全面 & 详细的设计模式学习指南 Carson带你 ...

  2. 一篇博客读懂设计模式之---模板方法模式

    设计模式之模板方法模式: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 简而言之就是:父类定义了骨架(调用哪些方法及其 ...

  3. 设计模式之模板方法模式详解

    设计模式之模板方法模式详解 概述 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的 ...

  4. Java设计模式之模板方法模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  5. php templete什么意思,PHP设计模式之模板方法模式定义与用法详解

    本文实例讲述了PHP设计模式之模板方法模式定义与用法.分享给大家供大家参考,具体如下: 什么是模板方法模式 模板方法(Template Method)设计模式中使用了一个类方法templateMeth ...

  6. 【设计模式】模板方法模式(C#)

    [设计模式]模板方法模式 1.概述 背景 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某 ...

  7. 设计模式之模板方法模式(TemplateMethod)

    设计模式之模板方法模式 模板方法模式 代码实现 模式的应用 模板方法模式 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现 ...

  8. 【Java】设计模式之模板方法模式

    - 好记性不如烂笔头,特将设计模式之模板方法模式记录在我的小仓库. 文章目录 什么是模板方法模式 案例 什么是模板方法模式 简而言之就是一套算法可以适用于多个类,则进行的步骤汇总,让子类别在不改变算法 ...

  9. C++设计模式之模板方法模式

    模板方法模式 设计模式的定义 模板方法模式详解 背景----柠檬茶和咖啡的的冲泡方式 代码实现咖啡和茶冲泡的类 整理相似点 进一步设计 总结一下 认识模板方法 测试一下 模板方法模式的优点 模板方法的 ...

最新文章

  1. Linux cpuidle framework(4)_menu governor
  2. strstr的应用---Hd 2054 A == B ?
  3. python做数据库管理系统_python+Django+mysql+bootstrap前端,数据库一次搞定)从头教你毕设实现一个简易好看的仓储物资管理之类系统...
  4. oracle 之 安装后pl/sql登录报ora-12154
  5. 品质标签分几种颜色_常见标签种类分析
  6. PyTorch 1.0 中文官方教程:迁移学习教程
  7. mysql jsp分页技术_一个非常简单的分页技术MYSQL JSP 利用了mysql的LIMIT参数
  8. Python学习-20180105
  9. 轻轻松松实现角度转换(弧度度分秒)
  10. 大数据基础课02 从萌芽到爆发,大数据经历了哪些发展?
  11. html field属性,field标签属性详解
  12. JAVA后端应该学什么技术?
  13. Android——实现Home键功能
  14. android业余手机开发,赚钱心得
  15. 九连环的解法(收集)
  16. 关于前端的CSS命名
  17. AI虚拟鼠标--详细注释解析恩培3
  18. Firefox下载文件中文乱码问题
  19. 性能测试计划包含那些内容?这份从零开始实施的性能测试指南千万不能错过
  20. 开发运营必看,跳出雷区必须知道的微信小程序平台运营规范

热门文章

  1. 基于tensorflow2.0利用CNN与线性回归两种方法实现手写数字识别
  2. PAT_B_1082_C++(20分)
  3. oracle+查询主机地址,oracle函数:获取Internet主机名和ip地址
  4. python接口测试demo_python http接口自动化测试简单demo
  5. 动态调用类 java_Java动态调用类中方法
  6. springboot + redis
  7. eclipse打包jar发布到linux下运行出错(java.lang.ClassNotFoundException: cmd.WordCount$MyMapper )
  8. [二叉树]序列化二叉树 (剑指offer61)
  9. Homography
  10. 主成分分析和因子分析及其在R中的…