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

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

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

    I want to fly higher
    programming Explorer
    posts - 114,comments - 263,trackbacks - 0
    第二條:遇到多個(gè)構(gòu)造器參數(shù)時(shí)考慮用構(gòu)建器:
       
         1.靜態(tài)工廠(chǎng)和構(gòu)造器有幾個(gè)共同的局限性,它們都不能很好的擴(kuò)展到大量的可選參數(shù).如一個(gè)類(lèi)表示包裝食品外面顯示的營(yíng)養(yǎng)成分標(biāo)簽,標(biāo)簽中有些域是必須的,不過(guò)還有多個(gè)可選域。大多數(shù)產(chǎn)品在某幾個(gè)可選域中都有非0值。
         2.對(duì)于這樣的類(lèi),程序員一貫采用重疊構(gòu)造器(telescoping constructor)模式。在這種模式下,你提供第一個(gè)只有必要參數(shù)的構(gòu)造器,第二個(gè)構(gòu)造有一個(gè)可選參數(shù),第三個(gè)有兩個(gè)可選參數(shù),一次類(lèi)推,最后一個(gè)構(gòu)造器包含所有可選參數(shù)。
         3.要?jiǎng)?chuàng)建實(shí)例的時(shí)候,就是參數(shù)列表最短的構(gòu)造器,但其包含了要設(shè)置的所有參數(shù)-->
          不過(guò)如果參數(shù)是包括一些可選,可選可能有一個(gè)為0,如
          NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);這個(gè)構(gòu)造器調(diào)用通常需要許多你根本不想設(shè)置的參數(shù),但還是不能不為他們傳值。如這里給fat傳了一個(gè)0.
          這里如果僅僅是6個(gè)參數(shù)的話(huà),情況看起來(lái)好像不是特別糟。問(wèn)題是隨著參數(shù)數(shù)目的增加,其很快就失去了控制->
         4.一句話(huà):重疊構(gòu)造器模式可行,但是當(dāng)有許多參數(shù)的時(shí)候,客戶(hù)端代碼可能會(huì)很難編寫(xiě),并且依然難以閱讀。如果讀者想知道參數(shù)是神馬意思,必須很仔細(xì)的要數(shù)著這些參數(shù)來(lái)研究。一連串類(lèi)型相同的參數(shù)會(huì)導(dǎo)致一些微妙的錯(cuò)誤。如果client不小心點(diǎn)到了其中兩個(gè)參數(shù)的順序,編譯器也不會(huì)報(bào)錯(cuò),但是程序在運(yùn)行時(shí)會(huì)出現(xiàn)錯(cuò)誤的行為。
         5.遇到多構(gòu)造器參數(shù)的時(shí)候,還有第二種代替辦法,即JavaBeans模式。該模式下,調(diào)用一個(gè)無(wú)參構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象,然后調(diào)用setter方法來(lái)設(shè)置每個(gè)必要的參數(shù),以及每個(gè)相關(guān)的可選參數(shù).
          這種模式彌補(bǔ)了重疊構(gòu)造器模式的不足。說(shuō)的明白一點(diǎn),就是創(chuàng)建實(shí)例很容易,產(chǎn)生的代碼讀起來(lái)也很容易。
          不過(guò),JavaBeans模式自身有很?chē)?yán)重的缺點(diǎn)。因?yàn)闃?gòu)造過(guò)程被分到了幾個(gè)調(diào)用中,在構(gòu)造過(guò)程中JavaBean可能處于不一致的狀態(tài)。類(lèi)無(wú)法僅僅通過(guò)檢驗(yàn)構(gòu)造器參數(shù)的有效性來(lái)保證一致性。試圖使用處于不一致?tīng)顟B(tài)的對(duì)象,將會(huì)導(dǎo)致失敗。這種失敗與包含錯(cuò)誤的代碼大相徑庭,因?yàn)槠湔{(diào)試起來(lái)十分困難。
          另外不足的一點(diǎn)在于,JavaBeans模式阻止了類(lèi)做成不可變的可能,這就需要程序員付出額外的努力來(lái)保證它的線(xiàn)程安全。
          當(dāng)對(duì)象的構(gòu)造完成,并且不允許在解凍之前使用時(shí),通過(guò)手動(dòng)“凍結(jié)”對(duì)象,可以彌補(bǔ)這些不足。但是這種方式十分笨拙,在實(shí)踐中很少使用。此外,它甚至?xí)谶\(yùn)行時(shí)導(dǎo)致錯(cuò)誤,因?yàn)榫幾g器無(wú)法確保程序員會(huì)在使用之前先在對(duì)象上調(diào)用freeze方法。
          注:個(gè)人認(rèn)為freeze和鎖類(lèi)似吧,即保證使用之前先鎖住對(duì)象,這樣只有當(dāng)前線(xiàn)程可進(jìn)行操作;使用完畢調(diào)用解凍方法?釋放鎖-->
        6.第三種替代方法,既能保證向重疊構(gòu)造器模式那樣的安全性,也能保證向JavaBeans模式那么好的可讀性。這就是Builde模式的一種形式。不直接生成想要的對(duì)象,而是讓客戶(hù)端利用所有必要的參數(shù)調(diào)用構(gòu)造器或者靜態(tài)工廠(chǎng),得到一個(gè)builder對(duì)象。然后客戶(hù)端在builder上調(diào)用類(lèi)似setter的方法來(lái)設(shè)置每個(gè)相關(guān)的可選參數(shù)。最后客戶(hù)端調(diào)用無(wú)參的build方法來(lái)生成不可變的對(duì)象。這個(gè)builder是它構(gòu)造的類(lèi)的靜態(tài)的成員類(lèi)。
         builder的setter方法返回builder本身,以便可以把調(diào)用鏈接起來(lái),以下就是調(diào)用代碼:
         NutritionFact3 cocaCola = new NutritionFact3.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();
         這樣的客戶(hù)端代碼很容易編寫(xiě),更為重要的是,易于閱讀。builder模式模擬了具名的可選參數(shù),就是Ada和python一樣。
          注:Ada是一種表現(xiàn)能力很強(qiáng)的通用程序設(shè)計(jì)語(yǔ)言,它是美國(guó)國(guó)防部為克服軟件開(kāi)發(fā)危機(jī),耗費(fèi)巨資,歷時(shí)近20年研制成功的。它被譽(yù)為第四代計(jì)算機(jī)語(yǔ)言的成功代表。
         builder像個(gè)構(gòu)造器一樣,可以對(duì)其參數(shù)強(qiáng)加約束條件。build方法可以檢驗(yàn)這些約束條件,將參數(shù)從builer拷貝到對(duì)象中之后,并在對(duì)象域而不是builder域中對(duì)他們進(jìn)行檢驗(yàn)(:保護(hù)性拷貝:在檢查參數(shù)的有效性之前進(jìn)行,并且有效性檢查是針對(duì)拷貝之后的對(duì)象)。如果違反了任何約束條件,builder方法就應(yīng)該拋出IllegalStateException.異常的詳細(xì)信息應(yīng)該顯示出違反了哪個(gè)約束條件。
         對(duì)多個(gè)參數(shù)強(qiáng)加約束條件的另一種方式是:用多個(gè)setter方法對(duì)某個(gè)約束條件必須持有的所有參數(shù)進(jìn)行檢查。如果該約束條件沒(méi)有得到滿(mǎn)足,setter方法就會(huì)拋出IllegalArgumentException。這樣有個(gè)好處,就是一旦傳遞了無(wú)效參數(shù),立即就會(huì)發(fā)現(xiàn)約束條件失敗,而不是等著調(diào)用build方法。
         與構(gòu)造器相比,builder的略微優(yōu)勢(shì)在于,builder可以有多個(gè)可變參數(shù)。構(gòu)造器就像方法一樣,只能有一個(gè)可變參數(shù)。因?yàn)閎uilder利用單獨(dú)的方法來(lái)設(shè)置每個(gè)參數(shù),你想要多少個(gè)可變參數(shù),他們就可以有多少個(gè),直到每個(gè)setter方法都有一個(gè)可變參數(shù)。
         builder模式十分靈活,可以利用單個(gè)builder構(gòu)建多個(gè)對(duì)象。builder的參數(shù)可以在創(chuàng)建對(duì)象期間進(jìn)行調(diào)整,也可以隨著不同的對(duì)象兒改變。builder可以自動(dòng)填充某些域,例如每次創(chuàng)建對(duì)象時(shí)自動(dòng)增加序列號(hào)。
         設(shè)置了參數(shù)的builder生成了一個(gè)很好的抽象工廠(chǎng),即客戶(hù)端可將將這樣一個(gè)builder傳給方法,使得該方法能夠?yàn)榭蛻?hù)端創(chuàng)建一個(gè)或多個(gè)對(duì)象。要使用該方法,需要有一個(gè)類(lèi)型表示builder。1.5或者更新版本,用泛型即能滿(mǎn)足所有的builder,無(wú)論他們?cè)跇?gòu)建哪種類(lèi)型的對(duì)象。
         如:
         public interface Builder<T>
         {
          public T builder();
         }
         如,可以聲明NutritionFact3.Builder類(lèi)來(lái)實(shí)現(xiàn)Builder<NutritionFact3>
         帶有Builder實(shí)例的方法通常利用有限制的通配符類(lèi)型來(lái)約束構(gòu)建器的類(lèi)型參數(shù),如:
          Tree buildTree(Builder<? extends Node> nodeBuilder),構(gòu)建每個(gè)節(jié)點(diǎn)的方法,利用一個(gè)客戶(hù)端提供的Builder是來(lái)來(lái)構(gòu)建樹(shù)。
         Java中傳統(tǒng)的抽象工廠(chǎng)實(shí)現(xiàn)是Class對(duì)象,用newInstance方法充當(dāng)build方法的一部分。這種用法隱含著一些問(wèn)題。newInstance方法總是企圖調(diào)用類(lèi)的無(wú)參構(gòu)造器,這個(gè)構(gòu)造器可能根本不存在。如果來(lái)沒(méi)有可以訪(fǎng)問(wèn)的無(wú)參構(gòu)造器,你也不會(huì)收到編譯錯(cuò)誤。相反,客戶(hù)端代碼必須在運(yùn)行時(shí)處理InstaniationException或者IlleagalAccessExcepion.這樣既不雅觀,也不方便。newInstance方法還會(huì)傳播由無(wú)參構(gòu)造器拋出的任何異常,及時(shí)newInstance缺乏相應(yīng)的throws子句。換句話(huà)說(shuō),Class.newInstance破壞了編譯時(shí)的異常檢查,而B(niǎo)uilder接口彌補(bǔ)了這些不足。
         7.Builder模式確實(shí)也有其自身不足。為了創(chuàng)建對(duì)象,必須先創(chuàng)建它的構(gòu)建器。雖然創(chuàng)建構(gòu)建器的開(kāi)銷(xiāo)在實(shí)踐中可能不那么明顯,但是在某些十分注重性能的情況下,可能就成問(wèn)題了。Builder模式可能還比重疊構(gòu)造器模式更加冗長(zhǎng),因?yàn)樗挥性诤芏鄥?shù)的時(shí)候才使用,比如4個(gè)或者跟更多個(gè)參數(shù)。
         不過(guò)記住,你將來(lái)可能需要添加參數(shù)。如果一開(kāi)始就是用構(gòu)造器或者靜態(tài)工廠(chǎng),等到類(lèi)需要多個(gè)參數(shù)時(shí)才添加構(gòu)建器,就會(huì)無(wú)法控制。那些過(guò)時(shí)的構(gòu)造器或者靜態(tài)工廠(chǎng)顯得十分不協(xié)調(diào)。因此通常最好一開(kāi)始就是構(gòu)建器。
         簡(jiǎn)而言之,如果來(lái)的構(gòu)造器或者靜態(tài)工廠(chǎng)中有多個(gè)參數(shù)。設(shè)計(jì)這種類(lèi)時(shí),Builder模式是中不錯(cuò)的選擇。 特別是當(dāng)大多數(shù)參數(shù)都是可選的時(shí)候。與是用傳統(tǒng)的重疊構(gòu)造器模式相比,是用Builder模式的客戶(hù)端代碼更易于閱讀和編寫(xiě),構(gòu)建器也比JavaBeans更安全。

    部分源碼:
    package com.book.chap2.builder;

    /**
    * 營(yíng)養(yǎng)成分標(biāo)簽
    * <p>
    * 針對(duì)多個(gè)可選參數(shù)的構(gòu)造器,采用的重疊構(gòu)造器模式(telescoping constructor)
    *
    * @author landon
    * @since 1.6.0_35
    * @version 1.0.0 2013-1-8
    *
    */


    public class NutritionFacts
    {
       
    /** 分量,必須 */
       
    private final int servingSize;// required
        /** 一份分量,必須 */
       
    private final int servings;// required
        /** 卡路里,可選 */
       
    private final int calories;// optional
        /** 脂肪含量 ,可選 */
       
    private final int fat;// optional
        /** 鈉含量 ,可選 */
       
    private final int sodium;// optional
        /** 碳水化合物 ,可選 */
       
    private final int carbohydrate;// optional

       
    /**
         *
         * 構(gòu)造函數(shù)1,2個(gè)必須成分作為參數(shù)
         *
         * @param servingSize
         * @param servings
        
    */

       
    public NutritionFacts(int servingSize, int servings)
       
    {
           
    this(servingSize, servingSize, 0);
        }


       
    /**
         *
         * 構(gòu)造函數(shù)2,增加一個(gè)可選成分:卡路里
         *
         * @param servingSize
         * @param servings
         * @param calories
        
    */

       
    public NutritionFacts(int servingSize, int servings, int calories)
       
    {
           
    this(servingSize, servings, calories, 0);
        }


       
    /**
         *
         * 構(gòu)造函數(shù)3,又增加一個(gè)可選成分:脂肪
         *
         * @param servingSize
         * @param servings
         * @param calories
         * @param fat
        
    */

       
    public NutritionFacts(int servingSize, int servings, int calories, int fat)
       
    {
           
    this(servingSize, servings, calories, fat, 0);
        }


       
    /**
         *
         * 構(gòu)造函數(shù)4,繼續(xù)增加一個(gè)可選成分:鈉
         *
         * @param servingSize
         * @param servings
         * @param calories
         * @param fat
         * @param sodium
        
    */

       
    public NutritionFacts(int servingSize, int servings, int calories,
               
    int fat, int sodium)
       
    {
           
    this(servingSize, servings, calories, fat, sodium, 0);
        }


       
    /**
         *
         * 構(gòu)造函數(shù)5,擁有全部成分
         *
         * @param servingSize
         * @param servings
         * @param calories
         * @param fat
         * @param sodium
         * @param carbohydrate
        
    */

       
    public NutritionFacts(int servingSize, int servings, int calories,
               
    int fat, int sodium, int carbohydrate)
       
    {
           
    this.servingSize = servingSize;
           
    this.servings = servings;
           
    this.calories = calories;
           
    this.fat = fat;
           
    this.sodium = sodium;
           
    this.carbohydrate = carbohydrate;
        }

       
       
    public static void main(Stringargs)
       
    {
           
    //fat參數(shù)傳了一個(gè)0
            NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);
        }

    }


    package com.book.chap2.builder;

    /**
    *
    * 營(yíng)養(yǎng)成分標(biāo)簽
    * <p>
    * 利用JavaBeans模式
    *
    *@author landon
    *@since 1.6.0_35
    *@version 1.0.0 2013-1-8
    *
    */


    public class NutritionFacts2
    {
       
    private  int servingSize = -1;
       
    private  int servings = -1;
       
    private  int calories = 0;
       
    private  int fat = 0;
       
    private  int sodium = 0;
       
    private  int carbohydrate = 0;
       
       
    //無(wú)參構(gòu)造函數(shù)
        public NutritionFacts2()
       
    {
        }


       
    //Setters
       
       
    public void setServingSize(int servingSize)
       
    {
           
    this.servingSize = servingSize;
        }


       
    public void setServings(int servings)
       
    {
           
    this.servings = servings;
        }


       
    public void setCalories(int calories)
       
    {
           
    this.calories = calories;
        }


       
    public void setFat(int fat)
       
    {
           
    this.fat = fat;
        }


       
    public void setSodium(int sodium)
       
    {
           
    this.sodium = sodium;
        }


       
    public void setCarbohydrate(int carbohydrate)
       
    {
           
    this.carbohydrate = carbohydrate;
        }

       
       
    public static void main(Stringargs)
       
    {
            NutritionFacts2 cocaCola = new NutritionFacts2();
           
           
    //利用setters
            cocaCola.setServingSize(240);
            cocaCola.setServings(8);
            cocaCola.setCalories(100);
            cocaCola.setSodium(35);
            cocaCola.setCarbohydrate(27);
        }

    }


    package com.book.chap2.builder;

    /**
    *
    * 營(yíng)養(yǎng)成分標(biāo)簽
    * <p>
    * 使用buider構(gòu)建器模式來(lái)構(gòu)造多參數(shù)的類(lèi)
    *
    * @author landon
    * @since 1.6.0_35
    * @version 1.0.0 2013-1-8
    *
    */


    public class NutritionFact3
    {
       
    //均是final,不可變
       
       
    private final int servingSize;// required
        private final int servings;// required
        private final int calories;// optional
        private final int fat;// optional
        private final int sodium;// optional
        private final int carbohydrate;// optional

       
    public static class Builder
       
    {
           
    // 必須參數(shù)
            private final int servingSize;// required
            private final int servings;// required

           
    // 可選參數(shù)
            private int calories = 0;// optional
            private int fat = 0;// optional
            private int sodium = 0;// optional
            private int carbohydrate = 0;// optional

           
    // 必須參數(shù)必須通過(guò)通過(guò)構(gòu)造參數(shù)傳遞
            public Builder(int servingSize, int servings)
           
    {
               
    this.servingSize = servingSize;
               
    this.servings = servings;
            }


           
    // 構(gòu)建calories,返回本身,以便可以把調(diào)用連接起來(lái)
            public Builder calories(int calories)
           
    {
               
    this.calories = calories;
               
    return this;
            }


           
    // 構(gòu)建sodium
            public Builder sodium(int sodium)
           
    {
               
    this.sodium = sodium;
               
    return this;
            }


           
    // 構(gòu)建fat
            public Builder fat(int fat)
           
    {
               
    this.fat = fat;
               
    return this;
            }


           
    // 構(gòu)建carbohydrate
            public Builder carbohydrate(int carbohydrate)
           
    {
               
    this.carbohydrate = carbohydrate;
               
    return this;
            }


           
    //build,返回NutritionFact3
            public NutritionFact3 build()
           
    {
               
    return new NutritionFact3(this);
            }

        }


       
    // 隱藏構(gòu)造函數(shù)
        private NutritionFact3(Builder builder)
       
    {
            servingSize
    = builder.servingSize;
            servings
    = builder.servings;
            calories
    = builder.calories;
            fat
    = builder.fat;
            sodium
    = builder.sodium;
            carbohydrate
    = builder.carbohydrate;
        }

       
       
    public static void main(Stringargs)
       
    {
            NutritionFact3 cocaCola
    = new NutritionFact3.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();
        }

    }

    posted on 2013-03-15 15:21 landon 閱讀(2313) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): ProgramBook
    主站蜘蛛池模板: 一级毛片免费毛片一级毛片免费| 亚洲人成人伊人成综合网无码| 未满十八私人高清免费影院| 日本免费v片一二三区| 亚洲人成自拍网站在线观看| 妞干网免费视频在线观看| 亚洲成a人片在线观看中文app| 67pao强力打造国产免费| 亚洲日韩在线视频| 在免费jizzjizz在线播| 婷婷精品国产亚洲AV麻豆不片 | 亚洲精品成人久久| **毛片免费观看久久精品| 亚洲第一永久在线观看| **aaaaa毛片免费同男同女| 国产亚洲成归v人片在线观看 | 日韩精品久久久久久免费| 日韩精品亚洲aⅴ在线影院| 一区二区免费在线观看| 亚洲国产一级在线观看| 特黄特色大片免费| 精品国产精品久久一区免费式| 蜜芽亚洲av无码精品色午夜| 最新国产乱人伦偷精品免费网站 | 国产精品亚洲专区在线观看 | 国产亚洲一卡2卡3卡4卡新区| 成年人网站在线免费观看| 波多野结衣亚洲一级| 女人让男人免费桶爽30分钟| 在线a亚洲老鸭窝天堂av高清| 国产精品无码一区二区三区免费 | 国产午夜免费高清久久影院| 亚洲va国产va天堂va久久| 久久99青青精品免费观看| 久久久久亚洲精品天堂| 成年人视频在线观看免费| 色偷偷亚洲第一综合网| 国产亚洲美女精品久久久| 猫咪www免费人成网站| 久久久久亚洲精品无码网址| 中文字幕手机在线免费看电影 |