设计模式目录:html
设计模式 1 ——观察者模式java
设计模式 6 —— 单件模式post
设计模式 9 —— 模板方法模式this
概述
模板模式是一种行为设计模式,它的实现思路是,建立一个桩方法,而且定义一些步骤让子类来实现。模板方法定义了一个算法的执行步骤,或者说可以提供一种默认的实现,这种实现归纳一部分子类或者所有子类的共同部分。
举一个例子帮助理解,假设提供一种造房子的算法。算法的步骤就是模拟造房子的过程:建地基、建支撑,最后添加墙和窗户 – 1. Fundation,2. Pillars,3. Walls,4. Windows。最重要的一点就是不能改变此建造过程,好比不可能在没用地基的时候就开始建造窗户。这个例子中,咱们就建立了一个模板方法 – 将使用不一样的方法完成对房子的建造。
为了确保子类不能重写(override)这个模板方法,应当使用final。
由于设计为一些方法的具体实现留待子类中,因此不得不安排基类为一个抽象类
HouseTemple.java
1 package cn.telling.test.action; 2 3 /** 4 * 5 * @ClassName: HouseTemplate TODO 6 * @author xingle 7 * @date 2015-9-24 下午2:04:22 8 */ 9 public abstract class HouseTemplate { 10 // template method, final so subclasses can't override 11 public final void buildHouse() { 12 buildFoundation(); 13 buildPillars(); 14 buildWalls(); 15 buildWindows(); 16 System.out.println("House is built."); 17 } 18 19 // default implementation 20 private void buildWindows() { 21 System.out.println("Building Glass Windows"); 22 } 23 24 // methods to be implemented by subclasses 25 public abstract void buildWalls(); 26 27 public abstract void buildPillars(); 28 29 private void buildFoundation() { 30 System.out.println("Building foundation with cement,iron rods and sand"); 31 } 32 33 }
buildHouse()是模板方法并定义了在建造房子过程当中一系列方法的执行顺序。
WoodenHouse.java
1 package cn.telling.test.action; 2 3 /** 4 * 5 * @ClassName: WoodenHouse 6 * TODO 7 * @author xingle 8 * @date 2015-9-24 下午2:07:06 9 */ 10 public class WoodenHouse extends HouseTemplate{ 11 12 /** 13 * 14 * @Description: TODO 15 * @author xingle 16 * @data 2015-9-24 下午2:07:15 17 */ 18 @Override 19 public void buildWalls() { 20 System.out.println("Building Wooden Walls"); 21 22 } 23 24 /** 25 * 26 * @Description: TODO 27 * @author xingle 28 * @data 2015-9-24 下午2:07:15 29 */ 30 @Override 31 public void buildPillars() { 32 System.out.println("Building Pillars with Wood coating"); 33 } 34 35 }
此处也应当对其余方法进行重写,可是为了简便,此处没用完成。
GlassHouse.java
1 package cn.telling.test.action; 2 3 /** 4 * 5 * @ClassName: GlassHouse 6 * TODO 7 * @author xingle 8 * @date 2015-9-24 下午2:05:28 9 */ 10 public class GlassHouse extends HouseTemplate{ 11 12 /** 13 * 14 * @Description: TODO 15 * @author xingle 16 * @data 2015-9-24 下午2:05:39 17 */ 18 @Override 19 public void buildWalls() { 20 System.out.println("Building Glass Walls"); 21 } 22 23 /** 24 * 25 * @Description: TODO 26 * @author xingle 27 * @data 2015-9-24 下午2:05:39 28 */ 29 @Override 30 public void buildPillars() { 31 System.out.println("Building Pillars with glass coating"); 32 33 } 34 35 }
用一个测试程序来测试此处已完成的模板方法。
HouseClient.java
1 package cn.telling.test.action; 2 3 /** 4 * 5 * @ClassName: HousingClient TODO 6 * @author xingle 7 * @date 2015-9-24 下午2:06:33 8 */ 9 public class HousingClient { 10 public static void main(String[] args) { 11 12 HouseTemplate houseType = new WoodenHouse(); 13 14 // using template method 15 houseType.buildHouse(); 16 System.out.println("************"); 17 18 houseType = new GlassHouse(); 19 20 houseType.buildHouse(); 21 } 22 23 }
注意,client正在调用基类的模板方法而且依赖于不一样步骤的实现细节,即这些正在使用的方法,他们一些来着基类另外一些来自子类。上述程序的输出:
模板方法模式定义一个操做中算法的骨架,而将这些步骤延迟到子类中,模板方法使得子类能够不改变一个算法的结构便可从新定义该算法的某些特定步骤。
这个模式是用来建立一个算法的模板。什么是模板?如你所见的,模板就是一个方法。更具体地说,这个方法将算法定义成一组步骤,其中的任何步骤均可以是抽象的,由子类负责实现,这能够确保算法的结构保持不变,同时由子类提供部分实现。
用模板方法排序
java数组类的设计者提供给咱们一个方便的模板方法用来排序。
public static void sort(Object[] a) { if (LegacyMergeSort.userRequested) legacyMergeSort(a); else ComparableTimSort.sort(a); } /** To be removed in a future release. */ private static void legacyMergeSort(Object[] a) { Object[] aux = a.clone(); mergeSort(aux, a, 0, a.length, 0); }
其中 mergeSort() 方法包含排序算法,此算法依赖于compareTo() 方法的实现来完成算法。咱们须要实现compareTo()方法,“填补”模板方法的缺憾。
/** * Src is the source array that starts at index 0 * Dest is the (possibly larger) array destination with a possible offset * low is the index in dest to start sorting * high is the end index in dest to end sorting * off is the offset to generate corresponding low, high in src * To be removed in a future release. */ private static void mergeSort(Object[] src, Object[] dest, int low, int high, int off) { int length = high - low; // Insertion sort on smallest arrays 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; }
数组的排序模板方法已经提升了算法,可是你必须让这个模板方法知道如何比较鸭子。你所要作的事情就是,实现一个compareTo() 方法。
可是数组没法继承,该如何使用sort()?
sort() 的设计者但愿这个方法能使用于全部的数组,因此他们把sort() 变成事静态的方法,这样一来,任何数组均可以使用这个方法。它使用起来和它被定义在超类中是同样的。实际上,sort()并非真正定义在超类中,因此sort() 方法须要知道你已经实现了compareTo()方法,不然就没法进行排序。
要达到这一点,设计者利用了Comparable接口。你必须实现这个接口,提供这个接口所声明的方法,也就是compareTo()。
鸭子的实现:
1 package cn.telling.test.action; 2 3 /** 4 * 5 * @ClassName: Duck 6 * TODO 7 * @author xingle 8 * @date 2015-9-24 下午3:32:47 9 */ 10 public class Duck implements Comparable<Object>{ 11 //咱们须要让鸭子类实现Comparable 接口,由于咱们没法真的让鸭子数组去继承数组 12 private String name ; 13 private int weight; 14 15 public Duck(String name,int weight){ 16 this.name = name; 17 this.weight = weight; 18 } 19 20 public String toString(){ 21 return name+" weight"+weight; 22 } 23 24 /** 25 * 排序所要的方法 26 * @Description: TODO 27 * @param o 28 * @return 29 * @author xingle 30 * @data 2015-9-24 下午3:42:43 31 */ 32 @Override 33 public int compareTo(Object o) { 34 //compareTo() 须要传入一只鸭子,和自己这种鸭子作比较 35 Duck otherDuck = (Duck) o; 36 if(this.weight<otherDuck.weight){ 37 return -1; 38 } else if(this.weight == otherDuck.weight){ 39 return 0; 40 } else { 41 return 1; 42 } 43 } 44 }
测试排序鸭子的程序:
1 package cn.telling.test.action; 2 3 import java.util.Arrays; 4 5 /** 6 * 7 * @ClassName: DuckSortTestDrive 8 * TODO 9 * @author xingle 10 * @date 2015-9-24 下午3:35:44 11 */ 12 public class DuckSortTestDrive { 13 14 public static void main(String[] args) { 15 Duck[] ducks = { new Duck("D1", 8), new Duck("D2", 6), 16 new Duck("D3", 2),new Duck("D4", 5) }; 17 System.out.println("Bofore sorting "); 18 dispaly(ducks); 19 //调用Array类的静态方法sort(),让后将鸭子数组当作参数传入 20 Arrays.sort(ducks); 21 System.out.println("After sorting "); 22 dispaly(ducks); 23 } 24 25 /** 26 * TODO 27 * @param ducks 28 * @author xingle 29 * @data 2015-9-24 下午3:39:17 30 */ 31 public static void dispaly(Duck[] ducks) { 32 for(int i = 0;i<ducks.length;i++){ 33 System.out.println(ducks[i]); 34 } 35 36 } 37 38 }
执行结果: