国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Effective Java

2019-11-14 21:45:13
字體:
來源:轉載
供稿:網友
Effective java - 用builder代替構造器

靜態工廠和夠構造器有一個共同的局限性:遇到大量的參數時無法很好的擴展。

先說說構造器。其實field不多時重疊構造器(telescoping constructor)是個不錯的方法,易于編寫也易于調用,這種方式在參數數量較少時也很常見。但問題是參數很多(可能越來越多)時,比如(現在已經很難找到對多個參數進行重疊構造的代碼了,于是在這里直接引用一下書中的代碼):

public class NutritionFacts {    PRivate final int servingSize; // (mL) required    private final int servings; // (per container) required    private final int calories; // optional    private final int fat; // (g) optional    private final int sodium; // (mg) optional    private final int carbohydrate; // (g) optional    public NutritionFacts(int servingSize, int servings) {        this(servingSize, servings, 0);    }    public NutritionFacts(int servingSize, int servings, int calories) {        this(servingSize, servings, calories, 0);    }    public NutritionFacts(int servingSize, int servings, int calories, int fat) {        this(servingSize, servings, calories, fat, 0);    }    public NutritionFacts(int servingSize, int servings, int calories, int fat,            int sodium) {        this(servingSize, servings, calories, fat, sodium, 0);    }    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(String[] args) {    NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);}

為了讓創建實例的過程變得更加清晰,于是我們有另一中選擇——JavaBean模式。這個再熟悉不過了,如下:

public class NutritionFacts {    // Parameters initialized to default values (if any)    private int servingSize = -1;     private int servings = -1;     private int calories = 0;    private int fat = 0;    private int sodium = 0;    private int carbohydrate = 0;    public NutritionFacts() {    }    // Setters    public void setServingSize(int val) {        servingSize = val;    }    public void setServings(int val) {        servings = val;    }    public void setCalories(int val) {        calories = val;    }    public void setFat(int val) {        fat = val;    }    public void setSodium(int val) {        sodium = val;    }    public void setCarbohydrate(int val) {        carbohydrate = val;    }}

用起來雖然比只有一行的構造器多幾個步驟,但非常清晰:

public static void main(String[] args) {    NutritionFacts cocaCola = new NutritionFacts();    cocaCola.setServingSize(240);    cocaCola.setServings(8);    cocaCola.setCalories(100);    cocaCola.setSodium(35);    cocaCola.setCarbohydrate(27);}

相比只通過一個構造器創建實例,JavaBean模式的實例的構造過程被分成了好幾個過程。我們完全有可能在屬性不完整的情況下使用這個實例。按書中原文就是:

A JavaBean may be in a inconsistent state partway through its construction.

當然,我們也可以做一些操作使其在未完成的情況下無法使用,但我不想因此讓一個類變得越來越復雜。另外,我根本無法用JavaBean模式完全排除了將類設計成不可變(Immutable)的可能性。

此時,我們選擇使用Builder來解決這一問題。示例如下:

public class NutritionFacts {    private final int servingSize;    private final int servings;    private final int calories;    private final int fat;    private final int sodium;    private final int carbohydrate;    public static class Builder {        // Required parameters        private final int servingSize;        private final int servings;        // Optional parameters - initialized to default values        private int calories = 0;        private int fat = 0;        private int carbohydrate = 0;        private int sodium = 0;        public Builder(int servingSize, int servings) {            this.servingSize = servingSize;            this.servings = servings;        }        public Builder calories(int val) {            calories = val;            return this;        }        public Builder fat(int val) {            fat = val;            return this;        }        public Builder carbohydrate(int val) {            carbohydrate = val;            return this;        }        public Builder sodium(int val) {            sodium = val;            return this;        }        public NutritionFacts build() {            return new NutritionFacts(this);        }    }    private NutritionFacts(Builder builder) {        servingSize = builder.servingSize;        servings = builder.servings;        calories = builder.calories;        fat = builder.fat;        sodium = builder.sodium;        carbohydrate = builder.carbohydrate;    }}

調用起來非常清晰(模擬了具名參數),而且非常簡單:

public static void main(String[] args) {    NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)                .calories(100).sodium(35).carbohydrate(27).build();}

當然,Builder也有缺點。

  1. 創建實例前都要創建一個Builder實例。
  2. Builder模式編寫起來較為冗長。

但是,當構建一個實例需要很多步驟(或者很多讓人混淆的參數)的時候,Builder模式是個不錯的選擇。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 达拉特旗| 东乡族自治县| 周至县| 利辛县| 定州市| 理塘县| 台安县| 鹿泉市| 苏州市| 青岛市| 庆元县| 江都市| 武乡县| 甘德县| 双桥区| 麻栗坡县| 定边县| 中牟县| 张北县| 吐鲁番市| 彭州市| 兴化市| 监利县| 乌鲁木齐县| 平罗县| 澄城县| 东乌珠穆沁旗| 股票| 农安县| 滕州市| 巴东县| 璧山县| 当雄县| 永州市| 随州市| 抚顺市| 泰安市| 凉山| 即墨市| 罗江县| 永昌县|