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

首先,模版方法模式是用来封装算法骨架的,也就是算法流程

既然被称为模版,那么它肯定允许扩展类套用这个模版,为了应对变化,那么它也一定允许扩展类做一些改变

事实就是这样,模版方法模式封装了算法流程,但允许由子类负责实现某些步骤细节

二.举个例子

假设我们要开一家允许加盟的炸酱面店,我们拥有独家秘制的酱料配方,以及独特的制作工艺,美味只此一家,地球上大多数人每天都吃我们的炸酱面,所以我们有了大量的加盟者

为了盈利,我们当然不能公开制作工艺与酱料配方,但由于加盟者经营地域的差异,制作细节又存在差异,比如北京人喜欢吃细面硬面,陕西人喜欢吃宽面软面,我们也不能为了保护配方而让北京的加盟者继续卖我们的宽面

所以我们需要把制作工艺与保密配方保护起来,谁都不允许修改,同时把面条的制作以及烹煮方式公开出去,允许加盟者修改

那么,要如何实现这样的需求?

没错,模版方法就是为此而生的

-------

首先,我们需要建立模版类,把该保护的保护起来,把该公开的公开出去:

package TemplateMethodPattern;

/**
* @author ayqy
* 定义炸酱面模版类
*/
public abstract class Noodles {
public void cook(){
//制作面条
makeNoodles();
//制作酱料
makeSauce();
//烹煮面条
boilNoodles();
//添加酱料
addSauce();
} /**
* 把秘制酱料保护起来
*/
private void makeSauce(){
System.out.println("做好一份独家秘制酱料");
} /**
* 把添加剂量保护起来
*/
private void addSauce(){
System.out.println("添加适量的秘制酱料");
} public abstract void makeNoodles();
public abstract void boilNoodles();
}

定义好了模版,90%的工作就已经完成了,下面开始实现具体类

北京炸酱面:

package TemplateMethodPattern;

/**
* @author ayqy
* 实现北京炸酱面具体类
*/
public class BJNoodles extends Noodles{ @Override
public void makeNoodles() {
System.out.println("做好一份有北京特色的手工面");
} @Override
public void boilNoodles() {
System.out.println("按北京特色煮面法煮好面条");
}
}

陕西炸酱面:

package TemplateMethodPattern;

/**
* @author ayqy
* 实现陕西炸酱面具体类
*/
public class SXNoodles extends Noodles{ @Override
public void makeNoodles() {
System.out.println("做好一份有陕西特色的手工面");
} @Override
public void boilNoodles() {
System.out.println("按陕西特色煮面法煮好面条");
}
}

有了这些具体类,我们按照地域分配给加盟者就好了

三.效果示例

先实现一个测试类:

package TemplateMethodPattern;

/**
* @author ayqy
* 实现一个测试类
*/
public class Test {
public static void main(String[] args){
//创建北京炸酱面对象
Noodles bjnoodles = new BJNoodles();
//创建陕西炸酱面对象
Noodles sxnoodles = new SXNoodles(); System.out.println("北京炸酱面制作工艺:");
bjnoodles.cook();//做一份北京炸酱面
System.out.println("\n陕西炸酱面制作工艺:");
sxnoodles.cook();//做一份陕西炸酱面
}
}

运行结果:

四.多一点思考

上面的例子中,我们很轻松的实现了对算法骨架的封装,而且允许扩展类自定义某些步骤细节,似乎很轻松也很完美

那好,让我们改改需求吧:

最近提倡绿色健康生活,大家都喜欢吃点蔬菜,我们传统的炸酱面不得不与时俱进,做好之后还要添点蔬菜

但问题是有的地方并不喜欢添加蔬菜,他们习惯了老字号炸酱面的风味,坚决不要蔬菜

所以我们不能简单地改变制作工艺,添加一道工序来加蔬菜

-------

如果能在模版中定义一个可选的操作就再好不过了,让加盟者自己选择要不要加点儿蔬菜

于是,我们需要对之前的模版做一点点改动:

package TemplateMethodPattern;

/**
* @author ayqy
* 定义炸酱面模版类
*/
public abstract class Noodles {
private boolean wantVegetables = false;//要不要蔬菜 public void setWantVegetables(boolean wantVegetables) {
this.wantVegetables = wantVegetables;
} public void cook(){
//制作面条
makeNoodles();
//制作酱料
makeSauce();
//烹煮面条
boilNoodles(); //要不要添点儿蔬菜
if(wantVegetables)
addVegetables(); //添加酱料
addSauce();
} /**
* 把秘制酱料保护起来
*/
private void makeSauce(){
System.out.println("做好一份独家秘制酱料");
} /**
* 把添加剂量保护起来
*/
private void addSauce(){
System.out.println("添加适量的秘制酱料");
} /**
* 添加时令蔬菜
*/
public void addVegetables(){
//空的实现
} public abstract void makeNoodles();
public abstract void boilNoodles();
}

注意,为了添加可选的操作,我们做了这么几件事情:

  1. 定义标志变量(选/不选)
  2. 提供标志变量的setter,供扩展类选择
  3. 修改算法骨架,加入新的可选步骤
  4. 为新的步骤提供一个空的实现(注意,这一步很重要,提供空的实现而不是定义一个抽象方法,避免了对现有扩展类的修改,这个在模版方法模式的术语中被称为Hook钩子)

五.模版方法模式与策略模式

这两个模式都是用来封装算法的,让我们来对比一下:

  策略模式 模版方法模式
概念 封装算法步骤,允许子类选择已有的策略(步骤细节) 封装算法骨架(流程),允许由子类负责实现某些细节
实现方式 用组合来实现 用继承来实现
目标 实现了算法步骤的选择 实现了算法的流程控制
亮点 支持运行时动态改变步骤(策略) 支持运行时动态改变算法流程(用hook来实现)
具体步骤 把易于变化的同类算法细节(步骤)找出来,再定义一个算法族(接口)把它们封装起来 把算法骨架抽象出来并封装在基类(模版类)中
总结 封装步骤 封装流程

举个例子:

假设现在有一个算法,流程是A->B->C->D,C步骤的具体实现可能有c1,c2,c3三种不同方法

策略模式:

  1. 定义一个行为接口C,定义execute方法
  2. 实现具体类c1,c2,c3扩展自接口C(c1,c2,c3三种行为供调用者选择)
  3. 在基类中添加一个属性,类型为接口C,并提供setter
  4. 扩展自基类的具体类将通过调用setter来动态改变行为

模版方法模式:

  1. 定义基类(模版类),在基类中定义算法流程(把流程封装起来)
  2. 在基类中把C步骤定义为抽象方法
  3. 扩展自基类的具体类将提供自己的实现(c1,c2,c3或者其它)

设计模式之模版方法模式(Template Method Pattern)的更多相关文章

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

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

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

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

  3. 设计模式-03工厂方法模式(Factory Method Pattern)

    插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...

  4. 【设计模式】工厂方法模式 Factory Method Pattern

    在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...

  5. 二十四种设计模式:工厂方法模式(Factory Method Pattern)

    工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...

  6. 设计模式之工厂方法模式(Factory Method Pattern)

    一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...

  7. 模版方法模式(Template Method)

    1.概念 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计模式属于行为型 ...

  8. 【UE4 设计模式】工厂方法模式 Factory Method Pattern 及自定义创建资源

    概述 描述 又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式,或者多态工厂(Polymorphic Factory)模式 工厂父类负责定义创建产品对象的公共接口,而工厂子类 ...

  9. .NET设计模式(16):模版方法(Template Method)(转)

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

  10. 乐在其中设计模式(C#) - 模板方法模式(Template Method Pattern)

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

随机推荐

  1. 兼容谷歌、火狐、IE7.0以上浏览器div+css实现的带有蒙版的半透明弹窗效果[xyytit]

    整个页面变暗的蒙版效果,带有半透明边框的弹窗,用在网站里一定很酷. 最初见与奢饰品购物网站YMALL,后边研究了下,自己做了这个实例. 技术要点:css中几种透明样式的使用.不同的样式在不同的浏览器中 ...

  2. windows系统如何真正隐藏文件夹[转载]

    方法一(推荐)eg:现需隐藏e盘bak目录下的tools文件夹e:\bak\tools运行:cmd键入:attrib +s +a +h +r e:\bak\tools然后,你再进去看e盘bak目录下, ...

  3. MyEclipse2018.9.0设置全局编码

    1.windows->Preferences打开"首选项"对话框,左侧导航,导航到general->Workspace 右侧Text file encoding,选择O ...

  4. centos6.6 下 安装 php7 按 nginx方式

    1.安装必要的依赖库 > yum -y install gd zlib libjpeg libjpeg-devel libpng libpng-devel freetype freetype-d ...

  5. 使用springmvc从页面中获取数据,然后根据获得的参数信息进行修改,如果修改的数据中含有不是基本数据类型的参数。比如传的参数中有Date类型的数据时,需要我们进行参数类型转换。

    1.1 需求 在商品修改页面可以修改商品的生产日期,并且根据业务需求自定义日期格式. 1.2 需求分析 由于日期数据有很多格式,所以springmvc没办法把字符串转换成日期类型.所以需要自定义参数绑 ...

  6. linux,windows 可执行文件(ELF、PE)

    现在PC平台流行的可执行文件格式(Executable)主要是Windows下的PE(Portable Executable)和Linux的ELF(Executable Linkable Format ...

  7. PAT 1054 求平均值 (20)(代码+思路+测试用例)

    1054 求平均值 (20)(20 分) 本题的基本要求非常简单:给定N个实数,计算它们的平均值.但复杂的是有些输入数据可能是非法的.一个"合法"的输入是[-1000,1000]区 ...

  8. Codeforces 607A 动态规划

    A. Chain Reaction time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  9. TLS/SSL简单过程

    .wcf的认证分为两种 1.1 transport模式,在传输层完成认证(只能在传输层完成认证,利用硬件加速效率更高) a.在使用transport模式,非windows凭证的情况下默认使用TLS/S ...

  10. 2018.07.04 POJ 1654 Area(简单计算几何)

    Area Time Limit: 1000MS Memory Limit: 10000K Description You are going to compute the area of a spec ...