設計模式目錄: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 }
執行結果: