前言
當(dāng)我們面對具有大量可選成員變量的 Java 類時,創(chuàng)建這些對象的最佳方法是什么?通常有三種方法: 伸縮構(gòu)造函數(shù),JavaBean模式和構(gòu)建器模式。
構(gòu)造函數(shù)
UserInfo userInfo1 = new UserInfo("felord.cn", 28);
UserInfo xxxxxx = new UserInfo("felord.cn", "xxxxxx", 28);
UserInfo xxxxxx1 = new UserInfo("felord.cn", "xxxxxx", 28, LocalDateTime.now());
構(gòu)造函數(shù)通常需要可伸縮性,也就是參數(shù)列表需要重載。有些時候我不得不傳入null進(jìn)行初始化。
// 不合理的構(gòu)造使用示范
UserInfo xxxxxx = new UserInfo(null, null, 28);
而且不能直觀看出這些參數(shù)所代表的的含義,這有可能引發(fā)致命的錯誤,我們將同類型的username和address互換位置依然成功初始化了對象,不會顯式的引發(fā)構(gòu)建錯誤,這是不合理的。
IDEA 參數(shù)列表提示功能
另外如果參數(shù)列表比較長,有七八個的話,代碼是非常冗長的。
難道構(gòu)造函數(shù)一無是處嗎,當(dāng)然不是。胖哥在使用構(gòu)造參數(shù)時會確保構(gòu)造的參數(shù)列表不會太長,而且如果參數(shù)是可選的話,不會將其置于構(gòu)造函數(shù)中的。另外構(gòu)建不可變對象使用構(gòu)造函數(shù)也是極好的。
JavaBean
這種方式是最常用的創(chuàng)建對象的方法。只需要使用無參構(gòu)造函數(shù),然后為每個成員變量設(shè)置setter方法。
UserInfo userInfo = new UserInfo();
userInfo.setUsername("felord.cn");
userInfo.setAge(28);
這種方式之所以使用非常普遍是因為很多知名框架需要你采用這種模式,比如JSON類庫Jackson、Spring Framework還有絕大部分的ORM框架。
大多數(shù)情況下這種方式是可以勝任的。它的缺點在于我們需要兩步來完成對象的創(chuàng)建工作,另外它缺乏創(chuàng)建不可變對象的能力。
構(gòu)建器
構(gòu)建器其實在我之前的文章多次用到,Spring Security對HttpSecurity的配置就用到了該模式。構(gòu)建器不僅獲得了伸縮構(gòu)造函數(shù)的安全性,而且可讀性更好。
我們需要在目標(biāo)對象(這里是UserInfo)內(nèi)部創(chuàng)建了一個靜態(tài)類,通常簡單地稱為Builder。Builder聲明了一系列方法來設(shè)置對象屬性的值,然后將其返回Builder本身,完成所有調(diào)用后,我們調(diào)用Builder的無參build方法進(jìn)行目標(biāo)對象的初始化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
public class UserInfo { private String username; private String address; private Integer age; private LocalDateTime addTime; // 私有化無參構(gòu)造 private UserInfo() { } public static class Builder { private String username; private Integer age; private String address; private LocalDateTime addTime; public Builder username(String username) { this .username = username; return this ; } public Builder address(String address) { this .address = address; return this ; } public Builder age(Integer age) { this .age = age; return this ; } public Builder addTime(LocalDateTime addTime) { this .addTime = addTime; return this ; } public UserInfo build() { UserInfo userInfo = new UserInfo(); userInfo.username = this .username; userInfo.address = this .address; userInfo.age = this .age; userInfo.addTime = this .addTime; return userInfo; } } // 省略 getter } |
然后初始化對象就可以這么寫:
1
2
3
4
5
6
|
UserInfo userInfo = new UserInfo.Builder() .username( "felord.cn" ) .address( "xxxxxx" ) .age(28) .addTime(LocalDateTime.now()) .build(); |
這種寫法首先很流暢,而且可讀性更高,同時靈活度也得到了保證,可選參數(shù)更易處理。但是這種模式增加了我們代碼的書寫難度,需要進(jìn)行一些額外的定義。當(dāng)然你可以借助于Lombok框架的@Builder注解來直接使用構(gòu)建器模式,但是不是每個人都喜歡Lombok。
由于常用的第三方框架的原因,這種寫法的使用場景并不是那么寬泛。通常在定義一些配置時使用它。可參考在這篇文章的做法。
總結(jié)
在Java日常開發(fā)中構(gòu)造函數(shù)和JavaBean是我們最常用的創(chuàng)建對象的手段,構(gòu)建器的適用場景相對少了一些,但是在定義一些配置的時候還是非常有用的。好了今天就聊到這里,希望對你有所幫助。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.51cto.com/14901317/2523043