Effective Java之多个构造参数考虑用构建器(二)
靜態工廠方法和構造器都有一個共同的特點–>無法擴展到大量的參數。
對于大量的參數類,我們有以下方案:
1.重疊構造器。這個源碼中經常可以看到,例如HashMap:
也就是說每個HashMap調用的其實都是含有全部參數的構造器public HashMap(int initialCapacity, float loadFactor)
這種重疊構造器的方法在參數較少的時候,是一種不錯的選擇,可以參數多了的話呢?
參數順序容易混淆吧?每個參數的意義容易難看懂吧?冗余的代碼寫得太多了吧?
于是方案二出現了
2.javaBean模式
就是把這個類聲明成javabean,只需要調用他的無參構造方法,set,set,set就好了。
這樣就避免了很多重疊構造器的問題
但是問題是,set,set,set的連續使用讓javabean的構造過程分開來了,讓javabean處于不一致的狀態(狀態就是javabean的屬性集合,相鄰兩個set方法過后的javabean屬性不一樣,也就是狀態不一致),因此,有些不小心的程序員,在set,set,set方法之間使用了javabean,因此可能會導致錯誤。
有沒有更好的方案呢?
3.builder設計模式 以下是一個例子 public class User {private final String firstName; // 必傳參數private final String lastName; // 必傳參數private final int age; // 可選參數private final String phone; // 可選參數private final String address; // 可選參數private User(UserBuilder builder) {this.firstName = builder.firstName;this.lastName = builder.lastName;this.age = builder.age;this.phone = builder.phone;this.address = builder.address;}public String getFirstName() {return firstName;}public String getLastName() {return lastName;}public int getAge() {return age;}public String getPhone() {return phone;}public String getAddress() {return address;}public static class UserBuilder {private final String firstName;private final String lastName;private int age;private String phone;private String address;public UserBuilder(String firstName, String lastName) {this.firstName = firstName;this.lastName = lastName;}public UserBuilder age(int age) {this.age = age;return this;}public UserBuilder phone(String phone) {this.phone = phone;return this;}public UserBuilder address(String address) {this.address = address;return this;}public User build() {return new User(this);}} }*User*類的構造方法是私有的。也就是說調用者不能直接創建User對象。
*User*類的屬性都是不可變的。所有的屬性都添加了final修飾符,因此User是不可變的,并且在構造方法中設置了值。并且,對外只提供getters方法。
Builder模式使用了鏈式調用。可讀性更佳。
Builder的內部類構造方法中只接收必傳的參數,并且該必傳的參數適用了final修飾符,可選參數沒有final修飾符,因此可以用此builder修改。
調用builder構建User:
new User.UserBuilder("王", "小二").age(20).phone("123456789").address("亞特蘭蒂斯大陸").build();Builder模式好處和優點:
使用Builder模式必然會導致寫兩遍相關屬性的代碼和SETTER方法,看起來有點吃力不討好。
然而需要看到的是,客戶端代碼的可用性和可讀性得到了大大提高。與此同時,構造函數的參數數量明顯減少調用起來非常直觀。
用Builder的構造函數而不是set方法傳遞客戶需要的屬性。這樣做的好處在于,對象總是能被一次完整的實例化,這能避免對象不一致狀態帶來可能的錯誤。
總結
以上是生活随笔為你收集整理的Effective Java之多个构造参数考虑用构建器(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Effective Java之静态工厂代
- 下一篇: java美元兑换,(Java实现) 美元