<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    合工大很牛很牛牛

      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方法)在父類中寫好了,會調用父類里的各種方法來實現(boilingwaterbrewpouraddCondiments),這些方法有的會在父類中就已經實現,有的會放到子類中實現之。

    再把程序寫的更完善些:由于算法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 化的了 閱讀(1574) 評論(3)  編輯  收藏 所屬分類: 設計模式

    Feedback

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

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

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

    主站蜘蛛池模板: 亚洲欧洲日产韩国在线| 国产亚洲情侣一区二区无| 亚洲一级毛片免费观看| 在线免费观看亚洲| 亚洲精品欧洲精品| 亚洲一区在线免费观看| 亚洲专区一路线二| 免费看又爽又黄禁片视频1000| 一本大道一卡二大卡三卡免费| 一区免费在线观看| 亚洲一级特黄无码片| 在线人成免费视频69国产| 亚洲国产精品久久久久网站| 4444www免费看| 亚洲免费视频网址| 青草草在线视频永久免费| 免费无码午夜福利片| 亚洲熟女一区二区三区| 在线观看免费中文视频| 亚洲欧美日韩一区二区三区在线| 91免费在线视频| 久久久久无码精品亚洲日韩| 37pao成人国产永久免费视频| 亚洲一级特黄大片无码毛片| 一个人看的www免费视频在线观看| 成人黄动漫画免费网站视频 | 永久在线免费观看| 亚洲a级在线观看| 免费无码一区二区三区蜜桃大| 噜噜噜亚洲色成人网站∨| 久久久www成人免费毛片| 亚洲欧美日韩国产精品一区| 亚洲电影日韩精品| 1000部免费啪啪十八未年禁止观看 | 亚洲人成色99999在线观看| 亚洲AV无码一区二区三区国产 | 久久亚洲国产精品| 成人a免费α片在线视频网站| 久久久久亚洲av无码专区导航 | 国产精品观看在线亚洲人成网| 免费三级毛片电影片|