合工大很牛很牛牛

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            14 Posts :: 1 Stories :: 37 Comments :: 0 Trackbacks

           

          茶和咖啡是兩個功能類似的類:咖啡的制作包括boil water, brew, pour, add condiments四步,而沏茶的過程包括boil water, steep, pour, add lemon四步。

          它們的一,三兩步相同,二,四兩步類似,如下:

          class Coffee {

              public void boilWater() {

                  System.out.println("Boiling water");

              }

              public void brew() {

                  System.out.println("Brewing Coffee in the water");

              }

              public void pour() {

                  System.out.println("Pour Coffee in cup");

              }

              public void addCondiments() {

                  System.out.println("Add sugar and Milk in the coffee");

              }

          }

          class Tea {

              public void boilWater() {

                  System.out.println("Boiling water");

              }

              public void steep() {

                  System.out.println("Steep te                                                                                                                                         a in the water");

              }

              public void pour() {

                  System.out.println("Pour tea in cup");

              }              

              public void addLemon() {

                  System.out.println("Add lemon in the tea");

              }

          }

          為了減少重復,增加復用,我們給它們加一個共同的抽象父類:CaffeineBeverage。

          兩個子類中相同的部分移到了父類中,變成父類的方法;不同的部分在父類中寫成抽象方法,具體實現放到子類中(對比工廠方法,工廠方法是把對象的創建方法放到了子類中)。

          另外,添加了一個prepareRecipe方法,相當于“一鍵”功能(這個和façade pattern的一鍵功能是有區別的,這里“一鍵”是寫在抽象父類中,而在façade pattern里,是寫在客戶端和類庫之間的一個新增的類中)。如下:

          package javaapplication36;

          public class Main {

              public static void main(String[] args) {

                  CaffeineBeverage beverage = new Coffee();

                  beverage.prepareRecipe();

                  beverage = new Tea();

                  beverage.prepareRecipe();

              }

          }

          abstract class CaffeineBeverage {

              public void prepareRecipe() {

                  boilWater();

                  brew();

                  pour();

                  addCondiments();

              }

              public void boilWater() {

                  System.out.println("Boiling water");

              }

              public abstract void brew();

              public void pour() {

                  System.out.println("Pour into the cup");

              }

              public abstract void addCondiments();

          }

          class Coffee extends CaffeineBeverage {

              public void brew() {

                  System.out.println("Brewing Coffee in the water");

              }

              public void addCondiments() {

                  System.out.println("Add sugar and Milk in the coffee");

              }

          }

          class Tea extends CaffeineBeverage {

              public void brew() {

                  System.out.println("Steep the tea");

              }

              public void addCondiments() {

                  System.out.println("Add lemon in the tea");

              }

          }

          在以上代碼中:父類的prepareRecipe方法實際上就是所謂的Template 方法,template方法中所調用的其他函數,有的在父類中已經實現,有的會根據不同的子類,而采用不同的實現。

          Template pattern:即算法(prepareRecipe方法)在父類中寫好了,會調用父類里的各種方法來實現(boilingwaterbrewpour,addCondiments),這些方法有的會在父類中就已經實現,有的會放到子類中實現之。

          再把程序寫的更完善些:由于算法prepareRecipe是不會變動的,所以我們給它加上final,而對于addCondiments ,有的飲料有可能需要配料,而有的飲料根本不可能添加配料。(也就是說有的子類, prepareRecipe方法中需要執行addCondiments功能,而有的子類不需要。)

          為了不寫幾種重復prepareRecipe方法(prepareRecipe1, prepareRecipe2….每種方法只是有個別步驟不一樣),我們使用Hook方式來做(Hook就是指一個包含空內容的實體方法,不同于抽象方法),如下:

          package javaapplication36;

          public class Main {

              public static void main(String[] args) {

                  CaffeineBeverage beverage = new Coffee();

                  beverage.prepareRecipe();

                  beverage = new Tea();

                  beverage.prepareRecipe();

                  beverage = new Milk();

                  beverage.prepareRecipe();

              }

          }

          abstract class CaffeineBeverage {

              public void prepareRecipe() {

                  boilWater();

                  brew();

                  pour();

                  addCondiments();

              }

              public void boilWater() {

                  System.out.println("Boiling water");

              }

              public abstract void brew();

              public void pour() {

                  System.out.println("Pour into the cup");

              }

              public void addCondiments() { //HOOK,一個空方法,不做任何事情,繼承的子類根據需//要覆蓋或者保持它為空。

              }

          }

          class Coffee extends CaffeineBeverage {

              public void brew() {

                  System.out.println("Brewing Coffee in the water");

              }

              public void addCondiments() { //addCondiments重寫

                  System.out.println("Add sugar and Milk in the coffee");

              }

          }

          class Tea extends CaffeineBeverage {

              public void brew() {

                  System.out.println("Steep the tea");

              }

              public void addCondiments() { //addCondiments重寫

                  System.out.println("Add lemon in the tea");

              }

          }

          class Milk extends CaffeineBeverage { //沒有對addCondiments重寫

              public void brew() {

                  System.out.println("Brewing Milk in the water.");

              }

          }

          最后,我們試圖更進一步完善代碼,即使子類有addCondiments這個方法,我們也可以根據客戶端的需要,選擇在執行prepareRecipe的時候是否進行addCondiments這一步。

          package javaapplication36;

          import java.io.BufferedReader;

          import java.io.IOException;

          import java.io.InputStreamReader;

          import java.util.logging.Level;

          import java.util.logging.Logger;

          public class Main {

              public static void main(String[] args) {

                  CaffeineBeverage beverage = new Coffee();

                  beverage.prepareRecipe();

                  beverage = new Tea();

                  beverage.prepareRecipe();

                  beverage = new Milk();

                  beverage.prepareRecipe();

              }

          }

          abstract class CaffeineBeverage {

              public void prepareRecipe() {

                  boilWater();

                  brew();

                  pour();

                  if (customerWantCondiments()) {

                      addCondiments();

                  }

              }

              public void boilWater() {

                  System.out.println("Boiling water");

              }

              public abstract void brew();

              public void pour() {

                  System.out.println("Pour into the cup");

              }

              public void addCondiments() {

              }

              public boolean customerWantCondiments() {

                  return true;//相當于不做任何判斷就直接讓prepareRecipe執行addCondiments()

              }

          }

          class Coffee extends CaffeineBeverage {

              public void brew() {

                  System.out.println("Brewing Coffee in the water");

              }

              @Override

              public void addCondiments() {

                  System.out.println("Add sugar and Milk in the coffee");

              }

              @Override

              public boolean customerWantCondiments() {

                  String answer = getUserInput();

                  if (answer.startsWith("y")) {

                      return true;

                  }

                  else {

                      return false;

                  }

              }

              private String getUserInput() { //獲取輸入,確定是否要Condiments

                  System.out.println("Would you love some condiments? (y/n)");

                  BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

                  String answer = null;

                  try {

                      answer = in.readLine();

                  }

                  catch (IOException ex) {

                      Logger.getLogger(Coffee.class.getName()).log(Level.SEVERE, null, ex);

                  }

                  answer = answer.toLowerCase();

                  return answer;

              }

          }

          class Tea extends CaffeineBeverage {

              public void brew() {

                  System.out.println("Steep the tea");

              }

              @Override

              public void addCondiments() {

                  System.out.println("Add lemon in the tea");

              }

          }

          class Milk extends CaffeineBeverage {

              public void brew() {

                  System.out.println("Brewing Milk in the water.");

              }

          }

          再舉一例,很常見的,自定義類型數組的比較就是用到了Template pattern,如下:

          package javaapplication37;

          import java.util.Arrays;

          public class Main {

              public static void main(String[] args) {

                  Duck[] ducks = {new Duck("duck1", 10), new Duck("duck2", 13), new Duck("duck3", 9)};

                  displayDucks(ducks);

                  Arrays.sort(ducks);//Arrays相當于template pattern中的抽象父類,sort是該類中的//算法函數

                  displayDucks(ducks);

              }

              private static void displayDucks(Duck[] ducks) {

                  for (int i = 0; i < ducks.length; i++) {

                      System.out.println(ducks[i].toString());

                  }

              }

          }

          class Duck implements Comparable {

              String name;

              int weight;

              Duck(String name, int weight) {

                  this.name = name;

                  this.weight = weight;

              }

              @Override

              public String toString() {

                  return name + ":" + weight;

              }

              public int compareTo(Object o) { //compareTo方法相當于HOOK

                  Duck otherDuck = (Duck) o;

                  if (this.weight < otherDuck.weight) {

                      return -1;

                  }

                  else if (this.weight == otherDuck.weight) {

                      return 0;

                  }

                  else {

                      return 1;

                  }

              }

          }

          我們來看看Arrays這個類是如何使用template pattern的。

          public class Arrays {

          public static void sort(Object[] a) { //sort是算法函數

                  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) {

                   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;

                  }

          }

          }

          public interface Comparable<T> {

              public int compareTo(T o); //compareToHOOK

          }

          再舉一例,看看Swing中的JFrame是如何使用template pattern的:

          package javaapplication38;

          import java.awt.Graphics;

          import javax.swing.JFrame;

          public class Main {

              public static void main(String[] args) {

                  MyFrame frame = new MyFrame("my first frame");

              }

          }

          class MyFrame extends JFrame { //JFrame 相當于template pattern中的父類,而它里面的//update方法就是其算法函數

              public MyFrame(String title) {

                  super(title);

                  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                  this.setSize(300, 300);

                  this.setVisible(true);

              }

              public void paint(Graphics g) { //paintHOOK

                  super.paint(g);

                  String msg = "i rule";

                  g.drawString(msg, 100, 50);

              }

          }

          posted on 2008-07-09 15:38 化的了 閱讀(1582) 評論(3)  編輯  收藏 所屬分類: 設計模式

          Feedback

          # re: template pattern 2008-07-09 17:21 深圳朋悅速8酒店梅林店
          http://www.aygfsteel.com  回復  更多評論
            

          # re: template pattern 2008-07-09 19:20 leekiang
          貌似抽象類實現幾個方法,留幾個接口,實現的方法要調接口,這就是模板了。  回復  更多評論
            

          # re: template pattern 2008-07-09 22:23 化的了
          @leekiang
          其實模板的目的就是保持算法的穩定,然后就搞了一大堆類似工廠方法的東西。。。  回復  更多評論
            

          主站蜘蛛池模板: 如皋市| 城固县| 江孜县| 本溪市| 任丘市| 阳山县| 黄陵县| 海丰县| 灯塔市| 瑞丽市| 吴堡县| 基隆市| 西乌珠穆沁旗| 定日县| 邻水| 中西区| 修文县| 贞丰县| 沽源县| 宣威市| 蒙山县| 同心县| 雅安市| 新余市| 广西| 巨鹿县| 玉溪市| 岳阳县| 封丘县| 饶阳县| 青海省| 板桥市| 达孜县| 南京市| 农安县| 广元市| 兴文县| 北票市| 曲阜市| 康定县| 凭祥市|