1. 程式人生 > >考慮用構建器

考慮用構建器

框架 dwr

遇到多個構造器參數時要考慮用構建器

java

effective java

創建和銷毀對象



    • 2.1 參數的限制

    • 2.2 重疊構造器

    • 2.3 JavaBeans模式

    • 2.3.1 創建JavaBeans模式

    • 2.3.2 JavaBeans模式的劣勢

    • 2.4 構建器

    • 1. 構建器是什麽?

    • 2. 為什麽使用構建器?

    • 3 總結


1. 構建器是什麽?

構建器也是一種獲得類對象的方法,在前面我們介紹了通過 構造器靜態工廠方法 兩種方式來獲得類的對象。
這裏我們寫一個 Person 類,並為這個類加上構建器:

  1. 1public class Person {


  2. 2 private final String name;


  3. 3 private

    final int age;


  4. 4


  5. 5 private final String address;


  6. 6 private final String phone;


  7. 7


  8. 8 public static class Builder{


  9. 9 private final String name;


  10. 10 private final int age;


  11. 11


  12. 12 private String address = null;


  13. 13 private String phone = null;


  14. 14


  15. 15 public Builder(String name,int age){


  16. 16 this.name = name;


  17. 17 this.age = age;


  18. 18 }


  19. 19


  20. 20 public Builder address(String val){


  21. 21 address = val;


  22. 22 return this;


  23. 23 }


  24. 24


  25. 25 public Builder phone(String val){


  26. 26 phone = val;


  27. 27 return this;


  28. 28 }


  29. 29


  30. 30 public Person builder(){


  31. 31 return new Person(this);


  32. 32 }


  33. 33 }


  34. 34


  35. 35 private Person(Builder builder){


  36. 36 this.name = builder.name;


  37. 37 this.age = builder.age;


  38. 38 this.address = builder.address;


  39. 39 this.phone = builder.phone;


  40. 40 }


  41. 41


  42. 42 @Override


  43. 43 public String toString() {


  44. 44 return "name:"+name+" age:"+age+" address:"+address+" phone:"+phone;


  45. 45 }


  46. 46


  47. 47}


調用這個構建器的方式

public class PersonTest {    public static void main(String[] args) {
        Person p = new Person.Builder("tom", 18).address("深圳").phone("110").builder();
        System.out.println(p.toString());
    }
}

2. 為什麽使用構建器?

2.1 參數的限制

靜態工廠方法與構造器都有一個共同的局限性,就是它們不能很好的擴展到大量的可選參數。就像我們上面的那個Person 類,在實際中我們會有許多的屬性,性別、出生年月、愛好...對與這樣的類。

2.2 重疊構造器

我們初學的時候都會選擇 重疊構造器(telecoping constructor)模式 。在這種情況下,第一個構造器是實例化對象必須的參數,第二個會多一個參數,就這樣疊加,最後是一個有所有參數的構造器

  1. 1public class Person {


  2. 2 private final String name;


  3. 3 private final int age;


  4. 4


  5. 5 private final String address;


  6. 6 private final String phone;


  7. 7


  8. 8 public Person(String name, int age) {


  9. 9 this(name,age,null);


  10. 10 }


  11. 11


  12. 12


  13. 13 public Person(String name, int age, String address) {


  14. 14 this(name,age,address,null);


  15. 15 }


  16. 16


  17. 17 public Person(String name, int age, String address, String phone) {


  18. 18 super();


  19. 19 this.name = name;


  20. 20 this.age = age;


  21. 21 this.address = address;


  22. 22 this.phone = phone;


  23. 23 }


  24. 24


  25. 25 @Override


  26. 26 public String toString() {


  27. 27 return "name:"+name+" age:"+age+" address:"+address+" phone:"+phone;


  28. 28 }


  29. 29


  30. 30}


獲得對象

public class PersonTest {    public static void main(String[] args) {
        Person p = new Person("tom",18,null,"110");
        System.out.println(p.toString());
    }
}

在這個構造器中也許會有你不想要的參數,如果我們的參數變多了的話,情況就不會很好。
總結一句話:重疊構造器可行,但當有很多的參數的時候,客戶端的代碼就會很難編寫並且不容易閱讀我們在使用的時候,必須很仔細的看每一個參數的位置和含義。

2.3 JavaBeans模式

2.3.1 創建JavaBeans模式

這個時候我們還有一種替代的方式,這個就是JavaBeans模式。這種種模式下,使用無參的構造方法創建對象,然後調用setter 方法給屬性設置值

  1. 1public class Person {


  2. 2 private String name;


  3. 3 private int age;


  4. 4


  5. 5 private String address;


  6. 6 private String phone;


  7. 7


  8. 8 public void setName(String name) {


  9. 9 this.name = name;


  10. 10 }


  11. 11 public void setAge(int age) {


  12. 12 this.age = age;


  13. 13 }


  14. 14 public void setAddress(String address) {


  15. 15 this.address = address;


  16. 16 }


  17. 17 public void setPhone(String phone) {


  18. 18 this.phone = phone;


  19. 19 }


  20. 20


  21. 21 @Override


  22. 22 public String toString() {


  23. 23 return "name:"+name+" age:"+age+" address:"+address+" phone:"+phone;


  24. 24 }


  25. 25


  26. 26}


使用的方式,這個相比與重疊構造器更容易的創建了對象,同時讓代碼跟容易的閱讀。

public class PersonTest {    public static void main(String[] args) {
        Person p = new Person();
        p.setName("tom");
        p.setAge(18);
        p.setAddress("深圳");
        p.setPhone("110");
        System.out.println(p.toString());
    }
}

2.3.2 JavaBeans模式的劣勢

  • 構造的過程分到了幾個調用中,在構造JavaBeans的時候可能會不一致

  • 類無法僅僅通過檢驗構造器參數的有效性來保證一致性!

  • 對象的不一致會導致失敗,JavaBeans模式阻止了把類做為不可變的可能,需要程序員做額外努力來保證它線程安全。

2.4 構建器

  • 構建器的創建對象就比較易於創建與閱讀,線程安全

  • 等待所有的參數驗證通過才會build()對象。

  • 與構造器相比,builder 的微略優勢在,builder可以有多個可變(varargs)參數。構造器像方法一樣,只有一個可變參數。因為builder利用單獨的方法來設置每個參數,你想要多少個可變參數,他們就可以有多少個,知道每個setter方法都有一個可變參數。

  • builder模式非常靈活,可以理由單個builder構建多個對象。builder的參數可以在創建對象時進行調整

  • 設置了參數的builder生成一個很好的抽象工廠(Abstract Factory),也就是客戶端可以將這樣一個builder傳給方法,使該方法能為客戶端創建一個或者多個對象

  • builder也有自己的不足,就是創建對象就必須創建它的構建器。雖然創建構建器的開銷在實踐中可能不是很明顯註意性能的情況先,這個就是問題了。

  • builder模式還比重疊構造器模式更加的冗長,因此它會在參數多的時候使用。但是我們要知道,我們可能會在設計之後還要添加參數,所以已開始就用構建器還是比較好的。

3 總結

如果類的構造器或者靜態工廠中具有多個參數,設計這種類時,Builder模式就是不錯的選擇,特別是當大多數參數都是可選的時候。

  • 與重疊構造器相比,builder牧師的客戶端更易與閱讀和編寫

  • 與JavaBeans相比,更加的安全


本文出自 “程序人生” 博客,請務必保留此出處http://4254002.blog.51cto.com/4244002/1922742

考慮用構建器