博客地址  http://blog.csdn.net/ftx2540993425

下面横线以上内容是借鉴别人的,为了表达对作者的敬意,不做不恰当的修改,我个人的总结在后面。

周三,9:00,我刚刚坐到位置,打开电脑准备开始干活。

“小三,小三,叫一下其它同事,到会议室,开会”老大跑过来吼,带着淫笑。还不等大家坐稳,老
大就开讲了,
“告诉大家一个好消息,昨天终于把牛叉模型公司的口子打开了,要我们做悍马模型,虽然是第一个
车辆模型,但是我们有能力,有信心做好,我们一定要…(中间省略 20 分钟的讲话,如果你听过领导人的
讲话,这个你应该能够续上) ”
动员工作做完了,那就开始压任务了, “这次时间是非常紧张的,只有一个星期的时间,小三,你负责
在一个星期的时间把这批 10 万车模(注:车模是车辆模型的意思,不是香车美女那个车模)建设完成…”
“一个星期?这个…,是真做不完,要做分析,做模板,做测试,还要考虑扩展性、稳定性、健壮性
等,时间实在是太少了”还没等老大说完,我就急了,再不急我的小命就折在上面了!
“那这样,你只做实现,不考虑使用设计模式,扩展性等都不用考虑”老大又把我压回去了。
“不考虑设计模式?那…”
哎,领导已经布置任务了,那就开始死命的做吧,命苦不能怨政府,点背不能怪社会呀,然后就开始
准备动手做,在做之前先介绍一下我们公司的背景,我们公司是做模型生产的,做过桥梁模型、建筑模型、
机械模型,甚至是一些政府、军事的机密模型,这个不能说,就是把真实的实物按照一定的比例缩小或放
大,用于试验、分析、量化或者是销售等等,上面提到的牛叉模型公司专门销售车辆模型的公司,自己不
生产,我们公司是第一次从牛叉模型公司接单,那我怎么着也要把活干好,可时间很紧张呀,怎么办?

既然领导都说了,不考虑扩展性,那好办,我先设计个类图:

非常简单的实现,你要悍马模型,我就给你悍马模型,先写个抽象类,然后两个不同型号的模型实现
类,那我们把这个程序实现出来:
HummerModel 抽象类的程序清单如下:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* Hummer Model是悍马车辆模型的意思,不是悍马美女车模
*/
public abstract class HummerModel {
/*
* 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正
* 是要能够发动起来,那这个实现要在实现类里了
*/
public abstract void start();
//能发动,那还要能停下来,那才是真本事
public abstract void stop();
//喇叭会出声音,是滴滴叫,还是哔哔叫
public abstract void alarm();
//引擎会轰隆隆的响,不响那是假的
public abstract void engineBoom();
//那模型应该会跑吧,别管是人推的,还是电力驱动,总之要会跑
public abstract void run();
}

H1 型号悍马的定义如下:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 悍马车是每个越野者的最爱,其中H1最接近军用系列
*/
public class HummerH1Model extends HummerModel {
@Override
public void alarm() {
System.out.println("悍马H1鸣笛...");
}
@Override
public void engineBoom() {
System.out.println("悍马H1引擎声音是这样在...");
}
@Override
public void start() {
System.out.println("悍马H1发动...");
}
@Override
public void stop() {
System.out.println("悍马H1停车...");
}
/*
* 这个方法是很有意思的,它要跑,那肯定要启动,停止了等,也就是要调其他方法
*/
@Override
public void run() {
//先发动汽车
this.start();
//引擎开始轰鸣
this.engineBoom();
//然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭
this.alarm();
//到达目的地就停车
this.stop();
}
}

然后看悍马 H2 型号的实现:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* H1和H2有什么差别,还真不知道,真没接触过悍马
*/
public class HummerH2Model extends HummerModel {
@Override
public void alarm() {
System.out.println("悍马H2鸣笛...");
}
@Override
public void engineBoom() {
System.out.println("悍马H2引擎声音是这样在...");
}
@Override
public void start() {
System.out.println("悍马H2发动...");
}
@Override
public void stop() {
System.out.println("悍马H1停车...");
}
/*
* H2要跑,那肯定要启动,停止了等,也就是要调其他方法
*/
@Override
public void run() {
//先发动汽车
this.start();
//引擎开始轰鸣
this.engineBoom();
//然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭
this.alarm();
//到达目的地就停车
this.stop();
}
}

然后程序写到这里,你就看到问题了,run 方法的实现应该在抽象类上,不应该在实现类上,好,我们
修改一下类图和实现:

就把 run 方法放到了抽象类中,那代码也相应的改变一下,先看 HummerModel.java:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* Hummer Model是悍马车辆模型的意思,不是悍马美女车模
*/
public abstract class HummerModel {
/*
* 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正
* 是要能够发动起来,那这个实现要在实现类里了
*/
public abstract void start();
//能发动,那还要能停下来,那才是真本事
public abstract void stop();
//喇叭会出声音,是滴滴叫,还是哔哔叫
public abstract void alarm();
//引擎会轰隆隆的响,不响那是假的
public abstract void engineBoom();
//那模型应该会跑吧,别管是人退的,还是电力驱动,总之要会跑
public void run() {
//先发动汽车
this.start();
//引擎开始轰鸣
this.engineBoom();
//然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭
this.alarm();
//到达目的地就停车
this.stop();
}
}

下面是 HummerH1Model.java 程序清单:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 悍马车是每个越野者的最爱,其中H1最接近军用系列
*/
public class HummerH1Model extends HummerModel {
@Override
public void alarm() {
System.out.println("悍马H1鸣笛...");
}
@Override
public void engineBoom() {
System.out.println("悍马H1引擎声音是这样在...");
}
@Override
public void start() {
System.out.println("悍马H1发动...");
}
@Override
public void stop() {
System.out.println("悍马H1停车...");
}
}

下面是 HummerH2Model.java 的程序清单:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* H1和H2有什么差别,还真不知道,真没接触过悍马
*/
public class HummerH2Model extends HummerModel {
@Override
public void alarm() {
System.out.println("悍马H2鸣笛...");
}
@Override
public void engineBoom() {
System.out.println("悍马H2引擎声音是这样在...");
}
@Override
public void start() {
System.out.println("悍马H2发动...");
}
@Override
public void stop() {
System.out.println("悍马H2停车...");
}
}

类图修改完毕了,程序也该好了,提交给老大,老大一看,挺好,就开始生产了,并提交给客户使用
了,那客户是如何使用的呢?类图上增加一个 Client 类,就是客户,我们这个是用 main 函数来代替他使
用,类图如下:

然后看增加的 Client.java 程序,非常的简单:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 客户开始使用这个模型
*/
public class Client {
public static void main(String[] args) {
//客户开着H1型号,出去遛弯了
HummerModel h1 = new HummerH1Model();
h1.run(); //汽车跑起来了;
//客户开H2型号,出去玩耍了
HummerModel h2 = new HummerH2Model();
h2.run();
}
}

运行的结果如下:
              悍马H1发动...
              悍马H1引擎声音是这样在...
              悍马H1鸣笛...
              悍马H1停车...
              悍马H2发动...
              悍马H2引擎声音是这样在...
              悍马H2鸣笛...
              悍马H2停车...
非常非常的简单,那如果我告诉这就是模板方法模式你会不会很不屑呢?就这模式,太简单了,我一
直在使用呀,是的,你经常在使用,但你不知道这是模板方法模式,那些所谓的高手就可以很牛 X 的说“用
模板方法模式就可以实现…” ,你还要很崇拜的看着,哇,牛人,模板方法模式是什么呀?
然后我们继续回顾我们这个模型,回头一想,不对呀,需求分析的有点问题,客户要关心模型的启动,
停止,鸣笛,引擎声音吗?他只要在 run 的过程中,听到或看都成了呀,暴露那么多的方法干啥?好了,
我们重新修改一下类图:

好了,这才是模板方法模式,就是这个样子,我们只要修改抽象类代码就可以了,HummerModel.java
程序清单如下:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* Hummer Model是悍马车辆模型的意思,不是悍马美女车模
*/
public abstract class HummerModel {
/*
* 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正
* 是要能够发动起来,那这个实现要在实现类里了
*/
protected abstract void start();
//能发动,那还要能停下来,那才是真本事
protected abstract void stop();
//喇叭会出声音,是滴滴叫,还是哔哔叫
protected abstract void alarm();
//引擎会轰隆隆的响,不响那是假的
protected abstract void engineBoom();
//那模型应该会跑吧,别管是人退的,还是电力驱动,总之要会跑
final public void run() {
//先发动汽车
this.start();
//引擎开始轰鸣
this.engineBoom();
//然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭
this.alarm();
//到达目的地就停车
this.stop();
}
}

其他的子类都不用修改(如果要修改,就是把四个方法的访问权限由 public 修改 protected),大家请
看这个 run 方法, 他定义了调用其他方法的顺序, 并且子类是不能修改的, 这个叫做模板方法; start、 stop、
alarm、engineBoom 这四个方法是子类必须实现的,而且这四个方法的修改对应了不同的类,这个叫做基本
方法,基本方法又分为三种:在抽象类中实现了的基本方法叫做具体方法;在抽象类中没有实现,在子类
中实现了叫做抽象方法,我们这四个基本方法都是抽象方法,由子类来实现的;还有一种叫做钩子方法,
这个等会讲。
到目前为止,这两个模型都稳定的运行,突然有一天,老大又找到了我,
“客户提出新要求了,那个喇叭想让它响就响,你看你设计的模型,车子一启动,喇叭就狂响,赶快
修改一下” ,确实是设计缺陷,呵呵,不过是我故意的,那我们怎么修改呢?看修改后的类图:

增加一个方法,isAlarm(),喇嘛要不要响,这就是钩子方法(Hook Method),那我们只要修改一下抽
象类就可以了:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* Hummer Model是悍马车辆模型的意思,不是悍马美女车模
*/
public abstract class HummerModel {
/*
* 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正
* 是要能够发动起来,那这个实现要在实现类里了
*/
protected abstract void start();
//能发动,那还要能停下来,那才是真本事
protected abstract void stop();
//喇叭会出声音,是滴滴叫,还是哔哔叫
protected abstract void alarm();
//引擎会轰隆隆的响,不响那是假的
protected abstract void engineBoom();
//那模型应该会跑吧,别管是人推的,还是电力驱动,总之要会跑
final public void run() {
//先发动汽车
this.start();
//引擎开始轰鸣
this.engineBoom();
//喇嘛想让它响就响,不想让它响就不响
if(this.isAlarm()){
this.alarm();
}
//到达目的地就停车
this.stop();
}
//钩子方法,默认喇叭是会响的
protected boolean isAlarm(){
return true;
}
}

钩子方法模式是由抽象类来实现的,子类可以重写的,H2 型号的悍马是不会叫的,喇叭是个摆设,看
HummerH2Model.java 代码:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* H1和H2有什么差别,还真不知道,真没接触过悍马
*/
public class HummerH2Model extends HummerModel {
@Override
protected void alarm() {
System.out.println("悍马H2鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("悍马H2引擎声音是这样在...");
}
@Override
protected void start() {
System.out.println("悍马H2发动...");
}
@Override
protected void stop() {
System.out.println("悍马H1停车...");
}
//默认没有喇叭的
@Override
protected boolean isAlarm() {
return false;
}
}

那 H2 型号的模型都没有喇叭,就是按了喇叭也没有声音,那客户端这边的调用没有任何修改,出来的
结果就不同,我们先看 Client.java 程序:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 客户开始使用这个模型
*/
public class Client {
public static void main(String[] args) {
HummerH2Model h2 = new HummerH2Model();
h2.run(); //H2型号的悍马跑起来
}
}

运行的出来的结果是这样的:

悍马H2发动...
                  悍马H2引擎声音是这样在...
                  悍马H1停车...

那 H1 又有所不同了,它的喇叭要不要响是由客户来决定,其实在类图上已经标明了 setAlarm 这个方
法,我们看 HummerH1Model.java 的代码:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 悍马车是每个越野者的最爱,其中H1最接近军用系列
*/
public class HummerH1Model extends HummerModel {
private boolean alarmFlag = true; //是否要响喇叭
@Override
protected void alarm() {
System.out.println("悍马H1鸣笛...");
}
@Override
protected void engineBoom() {
System.out.println("悍马H1引擎声音是这样在...");
}
@Override
protected void start() {
System.out.println("悍马H1发动...");
}
@Override
protected void stop() {
System.out.println("悍马H1停车...");
}
@Override
protected boolean isAlarm() {
return this.alarmFlag;
}
//要不要响喇叭,是有客户的来决定的
public void setAlarm(boolean isAlarm){
this.alarmFlag = isAlarm;
}
}

这段代码呢修改了两个地方,一是重写了父类的 isAlarm()方法,一是增加了一个 setAlarm 方法,由
调用者去决定是否要这个功能,也就是喇叭要不要滴滴答答的响,哈哈,那我们看看 Client.java 的修改:

package com.cbf4life;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 客户开始使用这个模型
*/
public class Client {
public static void main(String[] args) {
//客户开着H1型号,出去遛弯了
HummerH1Model h1 = new HummerH1Model();
h1.setAlarm(true);
h1.run(); //汽车跑起来了;
}
}

运行的结果如下:
             悍马H1发动...
             悍马H1引擎声音是这样在...
             悍马H1鸣笛...
             悍马 H1 停车...

看到没,这个模型 run 起来就有声音了,那当然把 h1.setAlarm(false)运行起来喇叭就没有声音了,
钩子方法的作用就是这样滴。
那我们总结一下模板方法模式,模板方法模式就是在模板方法中按照一个的规则和顺序调用基本方法,
具体到我们上面那个例子就是 run 方法按照规定的顺序(先调用 start,然后再调用 engineBoom,再调用
alarm,最后调用 stop)调用本类的其他方法,并且由 isAlarm 方法的返回值确定 run 中的执行顺序变更,
通用类图如下:

其中 TemplateMethod 就是模板方法,operation1 和 operation2 就是基本方法,模板方法是通过汇总
或排序基本方法而产生的结果集。模板方法在一些开源框架中应用很多,它提供了一个抽象类,然后开源
框架写了一堆子类,在《XXX In Action》中就说明了,如果你需要扩展功能,可以继承了这个抽象类,然
后修改 protected 方法,再然后就是调用一个类似 execute 方法,就完成你的扩展开发,确实是一种简单
的模式。

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即

可重定义该算法的某些特定步骤。

适用性:

一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke 和Johnson 所描述过的“重

分解以一般化”的一个很好的例子[ OJ93 ]。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最

后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

控制子类扩展。模板方法只在特定点调用“hook ”操作(参见效果一节),这样就只允许在这些点进行扩展。

模板方法模式【Template Method Pattern 】相关推荐

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

    模式的定义与特点 模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤.它 ...

  2. 模板方法模式(Template Method Pattern)学习笔记

    模板方法模式可以所是最为常见的一种设计模式了,出乎很多人意料的是,很多人已经在他们的代码中用到了模板方法模式而没有意识到自己用到了这个模式,模板方法模式几乎可以在所有的抽象基类中找到. 通过模板方法模 ...

  3. 使用 C# (.NET Core) 实现模板方法模式 (Template Method Pattern)

    本文的概念内容来自深入浅出设计模式一书. 项目需求 有一家咖啡店, 供应咖啡和茶, 它们的工序如下: 咖啡: 茶: 可以看到咖啡和茶的制作工序是差不多的, 都是有4步, 其中有两步它们两个是一样的, ...

  4. 模板方法模式(Template Method Pattern)

    模板方法模式: (就是在抽象基类中定一个复用的方法!) 在一个方法中定一个算法的骨架,而将一些步骤延迟到子类中. 模板方法使得子类可以再不改变算法结构的情况下,重新定义算法中的某些步骤. 实例: 泡茶 ...

  5. Net设计模式实例之模板方法模式(Template Mothed Pattern)(1)

    一.模板方法模式简介(Brief Introduction) 模板方法模式(Template Method Pattern),定义一个操作中的算法骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不 ...

  6. 模板方法模式 Template method 行为型 设计模式(二十六)

    模板方法模式 Template method 上图为网上百度的一份简历模板截图 相信大家都有求职的经历,那么必然需要简历,写简历的时候,很可能你会网上检索一份简历模板,使用此模板的格式,然后替换为你的 ...

  7. JAVA设计模式(14) —行为型模板方法模式(Template Method)

    1 定义: 模板方法模式(Template Method) Define the skeleton of an algorithm in anoperation, deferring some ste ...

  8. java 模板方法_设计模式(java实现)_模板方法模式(Template method)

    设计模式(java实现)_模板方法模式(Template method) 模板方法模式是编程中经常用到到的模式.它定义了一个操作中的算法骨架,将某些步骤延迟到子类中实现.这样,新的子类可以在不改变一个 ...

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

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  10. 模板方法模式(Tempalte Method Pattern)

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

最新文章

  1. 【CVPR Oral】TensorFlow实现StarGAN代码全部开源,1天训练完
  2. WebSocket+MSE——HTML5 直播技术解析
  3. [Spark][Hive][Python][SQL]Spark 读取Hive表的小例子
  4. 【深度学习】实战深度学习检测疟疾
  5. MySQL · 引擎特性 · InnoDB 事务子系统介绍
  6. Sqlserver 通用存储过程(二) 联合主键
  7. 微服务开发过程中需要注意的若干事项
  8. 公司招聘中不能说的秘密,简历只有这么发才有希望
  9. 基于visual Studio2013解决面试题之0202上下排
  10. linux回到桌面的命令符_Linux终端命令快捷键汇总
  11. 比对软件Blast,Blast+,Diamond如何选
  12. from .onnxruntime_pybind11_state import * # noqa ddddocr运行报错
  13. 怎么调节PDF文件的尺寸大小?
  14. html如何让图片不失真,图片放大不失真的几种方法
  15. java中scanner关于hasnext等的问题
  16. 在maven中创建jsp依赖
  17. 华数java 知乎_BAT都有意,知乎为什么和腾讯走到了一起?
  18. WatchStor观察:剖析pNFS和文件系统的未来
  19. PHP代码的加密解密
  20. 万字精华总结RocketMQ的常见用法(案例+图)

热门文章

  1. 装IDT声卡时总是说检测到的硬件不受此IDT软件程序包支持安装将终止
  2. 来自安徽、关心安徽的朋友一定要看!快报记者3点准时登陆在线聊天 - 评说天下 - 19楼互动生活空间
  3. 2021年网络安全学习路线指导(含视频教程)
  4. “磁碟机”病毒技术分析报告
  5. Win10下如何清理优化C盘
  6. C盘清理最全攻略,用这几招轻松解决,不存在C盘爆红
  7. 笔记-神经网络滑模控制设计方法
  8. 淘宝钻石(信用)的等级
  9. Android最新flash播放器----支持安卓5.0+系统。
  10. HTTP的基础知识——IP、TCP(3次握手) 和 DNS