1.定义:

在一个方法中定义一个算法骨架,而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

2.类图:

 3.说明:

  1. 模版方法可以理解为一个方法里面包含了多个步骤的方法。该方法一般声明为final,防止被子类覆盖,保护了算法结构。
  2. 模版模式的“钩子方法”,允许通过钩子方法改名算法模版中的某些逻辑。
  3. 使用模版方法模式时,基类里面的方法是否都需要定义为抽象方法?这样子子类是否必须覆盖过多的方法。这点是需要根据实际情况考虑的。如果算法步骤切割的太细,会导致子类需要覆盖过多的方法(挺讨厌的),如果切割的不够细又会导致框架缺乏弹性。
  4. 好莱坞原则:别调用(找)我们,我们调用(找)你。目的在于解耦。
  5. 真实环境里学会选择周围的设计模式,同时也要识别设计模式的变体。例如jdk里面的Array类的sort排序方法就不是一个变体。
  6. 例子Arrays类的sort排序方法,InputStream类的read方法,JFrame类的paint方法

4.例子:Arras的排序方法,根据鸭子重量排序的例子

4.1Duck.java:

package com.test.design.template5;
//鸭子类。实现Comparable接口,需要覆盖一个compareTo的方法。
public class Duck implements Comparable<Object> {
private String name;
private int weight;
public Duck() {
// TODO Auto-generated constructor stub
}
public Duck(String name,int weight) {
this.name = name;
this.weight = weight;
}
@Override
public String toString() {
return name + ";" + weight;
}
@Override
public int compareTo(Object o) {
/*if(null == o) {
throw new Exception("");
}*/
Duck duck = (Duck)o;
if(this.weight < duck.weight) {
return -1;
} else if(this.weight == duck.weight) {
return 0;
} else {
return 1;
}
}
}

4.2TestDuck.java

package com.test.design.template5;

import java.util.Arrays;

//测试类
public class TestDuck {
public static void main(String[] args) {
Duck d1 = new Duck("鸭子1",11);
Duck d2 = new Duck("鸭子2",11);
Duck d3 = new Duck("鸭子3",13);
Duck d4 = new Duck("鸭子4",9);
Duck[] ducks = new Duck[4];
ducks[0] = d1;
ducks[1] = d2;
ducks[2] = d3;
ducks[3] = d4;
Arrays.sort(ducks);
for (int i = 0; i < ducks.length; i++) {
System.out.println(ducks[i].toString());
}
}
}

//输出结果:

鸭子4;9
鸭子1;11
鸭子2;11
鸭子3;13,排序正确。

如果我们看jdk中类Arrays类的sort(Object[] a)方法,会发现我们可以把sort(Object[] a)看作是一个模版方法,在里面调用了方法mergeSort(),在mergeSort方法里面传入了待排序的数组引用,同时在方法里面实现了排序。

待排序的数组自己覆盖了compareTo方法,所以具体根据什么排序是由待排序数组对象自己去实现的。根据compareTo的结果去判断是否调换数组元素的位置。直至所有的数组元素都根据定义好的规则排好序。

很明显,这不是“教科书式”的模版方法模式的例子。教科书式的模版方法模式,是定义一个抽象类,抽象类里面提供一个final的模版方法,在模版方法里面调用一系列的方法步骤,并且把需要子类去实现的步骤定义为抽象方法,让子类根据情况去具体实现。

jdk的作者希望Arrays提供一个静态方法,任何的对象数组都可以进行排序。于是定义了一个静态的sort方法,而被排序的对象内的每个元素自行提供比较大小的算法部分。虽然不是正宗的模版方法模式,但是却符合模版方法模式的精神。

//排序
public static void sort(Object[] a) {
Object[] aux = (Object[])a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
//排序
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
...
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
...
}

 5.总结 :

要了解什么情况使用这个模式。

能够在以后看框架代码的时候发现学过的模式。

能够识别该模式的变体。

Head First 设计模式笔记(模版方法模式)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. 【pattern】设计模式(2) - 模版方法模式

    前言 一晃一年又过了,还是一样的渣. 一晃2周又过去了,还是没有坚持写博客. 本来前2天说填一下SQL注入攻击的坑,结果看下去发现还是ojdbc.jar中的代码,看不懂啊.这坑暂时填不动,强迫在元旦最 ...

随机推荐

  1. 100211D Police Cities

    传送门 分析 看到这个题我们的第一反应自然是Tarjan缩点,在这之后我们可以发现实际只要在缩点之后所有出度或入度为0的点布置警察局就可以达到要求,我们用dpij表示考虑前i个出度或入度为0的点共布置 ...

  2. [转]MYSQL5.7版本sql_mode=only_full_group_by问题

    转至:https://www.cnblogs.com/zhi-leaf/p/5998820.html 具体出错提示: [Err] 1055 - Expression #1 of ORDER BY cl ...

  3. GetResponse() 基础连接已经关闭:服务器关闭了本应保持活动状态的连接

    1.原因: (1)KeepAlive默认为true,与internet保持持续连接 ,服务器关闭了连接,使用HttpWebResponse.GetResponse()出错 (2)HttpWebRequ ...

  4. c++位运算符 | & ^ ~ && ||,补码,反码

    一:简介 1 位逻辑运算符: & (位   “与”)  and       ^  (位   “异或”)       |   (位    “或”)   or       ~  (位   “取反” ...

  5. Centos7环境下FastRunner前端(FasterWeb)部署

    FastRunner前端安装 1.安装和创建Python虚拟环境 安装virtualenvwrapper 2.拉取代码 cd ~ # 环境当前用户home目录 git clone git@github ...

  6. Linux性能指标解释+Oracle性能指标解释

    Linux性能指标解释 类别 计数器名称 计数器描述 业界同行认可的资源阀值 memory Free(KB) 可用物理内存数 swap-in/out =0 Swap(KB) 已使用的虚拟内存数.在Li ...

  7. RGB颜色表-网址不见了看这里

    英文不翻译 翻译成中文

  8. Wannafly挑战赛28B(DP,思维,字符串)

    #include<bits/stdc++.h>using namespace std;int n;int nxt[3][100007];char buff[100007];const ch ...

  9. (Python OpenGL)【 0】关于VAO和VBO以及OpenGL新特性

    (Python OpenGL)关于新版OpenGL需要了解的: 随着OpenGL状态和固定管线模式的移除,我们不在用任何glEnable函数调用,而且也不会有glVertex.glColor等函数调用 ...

  10. CF385C Bear and Prime Numbers 数学

    题意翻译 给你一串数列a.对于一个质数p,定义函数f(p)=a数列中能被p整除的数的个数.给出m组询问l,r,询问[l,r]区间内所有素数p的f(p)之和. 题目描述 Recently, the be ...