前言

一晃一年又过了,还是一样的渣。

一晃2周又过去了,还是没有坚持写博客。

本来前2天说填一下SQL注入攻击的坑,结果看下去发现还是ojdbc.jar中的代码,看不懂啊。这坑暂时填不动,强迫在元旦最后一天写一篇出来吧。

正文

在所有的设计模式中,个人觉得最简单、易学易用、使用率也高的其实是 - 模版方法模式(Template Method)。

相对单例,singleton我实际开发其实还没自己写过。也不清楚哪些情况下会用到singleton。

但Template Method缺写过几次,虽然严格上说可能不是Template Method。但最近写的代码结构,都是与Template Method的结构很类似。

主要是:(个人简单的理解,不一定全面)

1、方法/类遵循单一职责、开闭原则。

单一职责:把方法拆成块,阅读方便。(代码简洁之道)

开闭原则:对扩展开放、修改关闭。

2、方法复用。实际业务代码中,有些逻辑就应该调一个方法。(见下面demo)

Demo

例子1:

新生报名,需要登记个人信息。现在已有的途径是:1、填写表格,交给学校。2、自己去学校web官网填写。  后面扩展的途径:a、手机登陆学校app填写。

i. 不管什么途径填写,必须登记的有:姓名、年龄。

ii. 针对不同的填写途径,可能存在附带必须条件。 附带条件如下:

1、出生日期。

2、兴趣爱好。

a、手机号码。

/** 学生信息 */
public class StudentBean {
public final static int TYPE_FORM = 1;
public final static int TYPE_WEB = 2;
public final static int TYPE_APP = 3;
/* 任何条件必须*/
private String name;
/* 任何条件必须*/
private int age;
/* TYPE_FORM必须*/
private Long birthday;
/* TYPE_WEB必须*/
private String hobby;
/* TYPE_APP必须*/
private String phoneNumber;
private int registerType; //...
}

一、什么是模版方法模式?

预先定义好一些步骤,按这些步骤一步一步的执行。好比:起床、刷牙、吃早餐、坐车、上班。

摘自baike:

无处不在的Template Method:如果你只想掌握一种设计模式,那么它就是Template Method

意图(Intent):定义一个操作中的算法骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。(《设计模式》GoF)

二、实现demo例子

// 模板类
public abstract class ParentClass {
/** 子类扩展方法:保存前 */
public void saveBefore(StudentBean bean){ }
/** 子类扩展方法:保存后 */
public abstract void saveAfter(StudentBean bean); /** 模版方法 */
public final void saveStudentInfo(StudentBean bean){
saveBefore(bean);
// dao.save(bean);// 保存进数据库
System.out.println(this.getClass().getSimpleName() + ": " + JSON.toJSONString(bean));
saveAfter(bean);
}
}
/**
* 填表登记形式必须登记:出生日期
*/
public class FormClass extends ParentClass {
@Override
public void saveAfter(StudentBean bean) {
//any code
} @Override
public void saveBefore(StudentBean bean) {
bean.setRegisterType(StudentBean.TYPE_FORM);
bean.setBirthday(20170102L);
}
}
/**
* web登记形式必须登记:兴趣爱好
*/
public class WebClass extends ParentClass {
@Override
public void saveAfter(StudentBean bean) {
//any code
} @Override
public void saveBefore(StudentBean bean) {
bean.setRegisterType(StudentBean.TYPE_WEB);
bean.setHobby("吃饭睡觉打豆豆");
}
}
/**
* app登记形式必须登记:电话号码
*/
public class AppClass extends ParentClass {
@Override
public void saveAfter(StudentBean bean) {
//any code
} @Override
public void saveBefore(StudentBean bean) {
bean.setRegisterType(StudentBean.TYPE_APP);
bean.setPhoneNumber("");
}
}

说明:ParentClass是模版方法类。FormClass、WebClass、AppClass都是具体实现。

// 测试
public class TestTemplate {
private static StudentBean f = new StudentBean("form",1);
private static StudentBean w = new StudentBean("web",2);
private static StudentBean a = new StudentBean("app",3);
public static void main(String[] args) {
FormClass form = new FormClass();
form.saveStudentInfo(f); WebClass web = new WebClass();
web.saveStudentInfo(w); AppClass app = new AppClass();
app.saveStudentInfo(a);
}
}
// 测试结果
FormClass: {"age":1,"name":"form","birthday":20170102,"registerType":1}
WebClass: {"age":2,"name":"web", "hobby":"吃饭睡觉打豆豆","registerType":2}
AppClass: {"age":3,"name":"app", "phoneNumber":"","registerType":3}

三、解析

模版方法模式的核心是:1、对象优先调用本身的属性/方法。2、对象类本身没有的属性/方法,根据继承关系,依次查找其直接父类并调用。

在demo中,在具体子类FromClass、WebClass、AppClass中都未定义saveStudentInfo()方法,所以调用的都是ParentClass中的saveStudentInfo()。

然而,在ParentClass中定义了saveBefore()、声明了saveAfter()。但是,因为最后调用saveStudentInfo()的对象是FormClass、WebClass、AppClass。

所以,并没有用到ParentClass中的saveBefore()、saveAfter()。(优先使用对象自身的属性/方法)

其次对于demo中各部分声明的修饰符,可以根据实际情况选择。

例如demo:为了确保模版方法不被重写,所以用final修饰了saveStudentInfo()方法;

为了确保方法需要被重写(正常的Template Method可能都是有一套默认算法,以此保证默认的模版方法可用。即ParentClass不是抽象类,saveStudentInfo()默认有一套实现),所以我定义了抽象方法saveAfter()。

四、重点

1、很明显的违反SOLID中的L(Liskov Substitution Principle) - 里氏替换原则 : 任何父类可以出现的地方,子类一定可以出现。

但设计原则并不是强制约束,而且模版方法模式本身其实就不算是重写模版方法,而是实现/完整了模版方法。最终不管是子类/父类调模版方法,其目的、结果是没变的。

2、个人觉得模版方法的写法很推荐。即单一职责,把方法拆分开,每个方法只做自己份内的“一件事”。

例如excel导入数据,可以一个方法把:验证excel数据、excel转换JavaBean、保存JavaBean,都写在一个300行的代码中。也可以写在3个方法,每个方法100行。

多看各种源码、《代码简洁之道》、《代码之美》多体验下SOLID,体验代码和代码之间的区别。

【pattern】设计模式(2) - 模版方法模式的更多相关文章

  1. 设计模式之模版方法模式(Template Method Pattern)

    一.什么是模版方法模式? 首先,模版方法模式是用来封装算法骨架的,也就是算法流程 既然被称为模版,那么它肯定允许扩展类套用这个模版,为了应对变化,那么它也一定允许扩展类做一些改变 事实就是这样,模版方 ...

  2. JS常用的设计模式(10)——模版方法模式

    模式方法是预先定义一组算法,先把算法的不变部分抽象到父类,再将另外一些可变的步骤延迟到子类去实现.听起来有点像工厂模式( 非前面说过的简单工厂模式 ). 最大的区别是,工厂模式的意图是根据子类的实现最 ...

  3. 设计模式 笔记 模版方法模式 Template Method

    //---------------------------15/04/28---------------------------- //TemplateMethod 模版方法模式----类行为型模式 ...

  4. JAVA设计模式之模版方法模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述模板方法(Template Method)模式的: 模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式 ...

  5. java设计模式之模版方法模式以及在java中作用

    模板方法模式是类的行为模式.准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有 ...

  6. [Head First设计模式]云南米线馆中的设计模式——模版方法模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  7. 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)

    原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...

  8. NET设计模式 第二部分 行为型模式(15):模版方法模式(Template Method)

    摘要:Template Method模式是比较简单的设计模式之一,但它却是代码复用的一项基本的技术,在类库中尤其重要. 主要内容 1.概述 2.Template Method解说 3..NET中的Te ...

  9. 设计模式——模版方法模式详解(论沉迷LOL对学生的危害)

    .  实例介绍 在本例中,我们使用一个常见的场景,我们每个人都上了很多年学,中学大学硕士,有的人天生就是个天才,中学毕业就会微积分,因此得了诺贝尔数学奖:也有的人在大学里学了很多东西,过得很充实很满意 ...

随机推荐

  1. 关于AR眼镜的小结

    根据IDC(International Data Corporation,国际数据公司,IDC是全球著名的信息技术.电信行业和消费科技咨询.顾问和活动服务专业提供商)的报告,2018年AR和VR的产值 ...

  2. 微信小程序开发技巧总结 (一)-- 数据传递和存储

    结合自己在平时的开发中遇到的各种问题,和浏览各种问题的解决方案总结出一些自己在日常开发中常用的技巧和知点,希望各位不吝斧正. 1.短生命周期数据存储 以小程序启动到彻底关闭为周期的的数据建议存储在ap ...

  3. 《C# 爬虫 破境之道》:第二境 爬虫应用 — 第四节:小说网站采集

    之前的章节,我们陆续的介绍了使用C#制作爬虫的基础知识,而且现在也应该比较了解如何制作一只简单的Web爬虫了. 本节,我们来做一个完整的爬虫系统,将之前的零散的东西串联起来,可以作为一个爬虫项目运作流 ...

  4. git push 的解决方案

    如果输入$ git push origin master 提示出错信息: 或者 失败的原因:不能 push 远端仓库 原因分析:由于你当前分支落后与远程端对应分支,所以无法更新: 解决方案:使用 gi ...

  5. [1天搞懂深度学习] 读书笔记 lecture I:Introduction of deep learning

    - 通常机器学习,目的是,找到一个函数,针对任何输入:语音,图片,文字,都能够自动输出正确的结果. - 而我们可以弄一个函数集合,这个集合针对同一个猫的图片的输入,可能有多种输出,比如猫,狗,猴子等, ...

  6. 踩坑ThinkPHP5之模型对象返回的数据集如何转为数组

    各位小伙伴们大家好,冷月今天在做项目的过程中呢,遇到了一个坑就是用tp5的模型操作数据库时,返回的是数据集而不是直接的数组.于是冷月就想办法如何将数据集转为数组.写下这篇博文,防止大家遇到这个坑时可以 ...

  7. pytorch之 RNN 参数解释

    上次通过pytorch实现了RNN模型,简易的完成了使用RNN完成mnist的手写数字识别,但是里面的参数有点不了解,所以对问题进行总结归纳来解决. 总述:第一次看到这个函数时,脑袋有点懵,总结了下总 ...

  8. Load_file 常用路径

    load_file 常用路径 WINDOWS下: c:/boot.ini //查看系统版本 c:/windows/php.ini //php配置信息 c:/windows/my.ini //MYSQL ...

  9. JVM性能优化系列-(6) 晚期编译优化

    6. 晚期编译优化 晚期编译优化主要是在运行时做的一些优化手段. 6.1 JIT编译器 在部分的商用虚拟机中,java程序最初是通过解释器(Interpreter) 进行解释执行的,当虚拟机发现某个方 ...

  10. css3新增边框、阴影、边框、背景、文本、字体

    css3和css有什么区别?简单来讲css3是css(层叠样式表)技术的升级版本,css3新特征有很多,例如圆角效果.图形化边界.块阴影与文字阴影.使用RGBA实现透明效果.渐变效果.使用@Font- ...