如何更好地建立物件
寫Java一類的面相物件語言的程式設計師常常會遇到這麼一個冷笑話:我今年都30了,還沒找到物件,怎麼辦?簡單啊,new 一個物件就好。
當然這只是一個冷笑話,所謂的 new 一個物件,無非不就是呼叫這個類的構造方法去建立物件。乍一看也沒什麼問題,寫個類ABC,用的時候new ABC()就好了。那麼,會想一下,我們讀書的時候,老師一定會說一個類的構造方法可以允許傳入引數,甚至根據傳入引數的不同建立多個構造方法。
學過物件導向的你一定會說,沒錯啊,就是這樣,方法過載,簽名校驗。都是一個方法,Perfect!那麼,我們設想下面這麼一種情況:
假如我們有一個DTO類 CredentialsAuthParam 作為對外介面的傳入引數,作為一個POJO類,我們一般就是定義一堆屬性,然後一堆Getter、Setter,比如,我們可以這麼定義:
package me.yufan.dto;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Serializable;
public class CredentialsAuthParam implements Serializable {
private static final long serialVersionUID = -1L;
private String source;
private String validationCode;
private String operator;
private String remark;
public CredentialsAuthParam() {
}
public String getValidationCode() {
return validationCode;
}
public void setValidationCode(String validationCode) {
this.validationCode = validationCode;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.SHORT_PREFIX_STYLE);
}
}
看著很棒,多麼簡單,用 CredentialsAuthParam 的時候 new 一下,作為傳入引數呼叫介面的方法就好。
那麼,如果我的物件要設定屬性怎麼辦?一個個Setter?為何不能在建立物件時建立呢?比如,構造方法裡面指定引數?沒錯,然後我們就有了下面的一堆構造方法。
public CredentialsAuthParam(String source, String validationCode) {
this.source = source;
this.validationCode = validationCode;
}
public CredentialsAuthParam(String source, String validationCod, String operator) {
this.source = source;
this.validationCode = validationCode;
this.operator = operator;
}
public CredentialsAuthParam(String source, String validationCod,
String operator, String remark) {
this.source = source;
this.validationCode = validationCode;
this.operator = operator;
this.remark = remark;
}
那麼問題來了,引數這麼多,又都是String,建立一個物件多麻煩。又比如,我只想指定其中3個屬性,又都是String,但現在已經有了一個為3個String 引數的構造方法。怎麼辦?
Java對方法過載的判斷是按照簽名的型別進行校驗。所以方法引數順序需要開發在使用時自己指定,也許我方法引數是:String source, String validationCode。但結果我因為複製貼上不仔細變成了this.source = validationCode; this.validationCode = source;(別笑,你忙著寫垃圾程式碼的時候就會出錯) 或者構造方法使用者弄混了兩個引數的順序。那麼就會出事啦。
其實如果你看過Java聖經Effective Java的話,一定會注意到裡面說過構造器(Builder),多個引數的構造方法一定要考慮使用構造器。比如,我們可以這麼寫:
package me.yufan.dto;
public class CredentialsAuthParamBuilder {
private String source = "";
private String validationCode;
private String operator = "";
private String remark = "";
public CredentialsAuthParamBuilder setSource(String source) {
this.source = source;
return this;
}
public CredentialsAuthParamBuilder setValidationCode(String validationCode) {
this.validationCode = validationCode;
return this;
}
public CredentialsAuthParamBuilder setOperator(String operator) {
this.operator = operator;
return this;
}
public CredentialsAuthParamBuilder setRemark(String remark) {
this.remark = remark;
return this;
}
public CredentialsAuthParam createCredentialsAuthParam() {
return new CredentialsAuthParam(source, validationCode, operator, remark);
}
}
然後將原來類的構造方法定義為Protected,然後建立物件的時候只需要:
new CredentialsRequestParamBuilder()
.setRemark("remark")
.createCredentialsRequestParam();
按照需求,設定幾個屬性就加幾個 set 方法。
接下來,我們說說單例模式:
單例(Singleton),顧名思義,就是隻被例項化一次的類。比如,我在MVC的攔截器中需要呼叫一個公共類,它裡面存放的東西是大家共享的,我可以這麼寫:
public class AuthorityInterceptorHelper {
private static AuthorityInterceptorHelper instance;
private AuthorityInterceptorHelper() {
}
public static AuthorityInterceptorHelper getInstance() {
if (instance == null) {
synchronized (AuthorityInterceptorHelper.class) {
if (instance == null) {
instance = new AuthorityInterceptorHelper();
}
}
}
return instance;
}
// other code ...
}
我首先要在內部定義一個自身的靜態物件,然後將構造方法私有,getInstance()會先去看靜態物件存在否,不存在,先加鎖,也許加鎖期間其他方法先呼叫此方法建立物件,再看看物件是否存在,不存在,建立物件解鎖。
看起來沒什麼問題,程式碼嚴密,十分規範,大家都是這麼寫的。但是,單例了麼?定義為私有的方法一定沒法訪問了麼?反射呢?
其實列舉類便可以輕鬆實現需求,我們只需如下寫法:
public enum AuthorityInterceptorHelper {
INSTANCE;
// other function ...
}
相關文章
- 如何讓Designer更好地運算元據庫物件物件
- 如何更好地學習機器學習?機器學習
- Node 中如何更好地打日誌
- 如何更好地緩解網路攻擊
- 如何在 JavaScript 中更好地使用陣列JavaScript陣列
- 如何建立更好的混合雲平臺
- 如何用Map物件建立Set物件物件
- 如何更好地設計手機軟體介面
- 遊戲情節如何更好地讓玩家共情?遊戲
- 更好地程式設計程式設計
- [譯文] 如何在 JavaScript 中更好地使用陣列JavaScript陣列
- 如何更好地開發一個Android應用Android
- javascript如何建立一個物件JavaScript物件
- 更好地使用 ViewControllerViewController
- 探究如何通過CRM系統更好地經營企業?
- 【譯】更好地設計 React 元件React元件
- Mac:更好地工作 – 系統配置Mac
- 如何優雅地列印一個Java物件?Java物件
- 區塊鏈如何更好地改進雲端計算解決方案區塊鏈
- 如何建立一個“純淨”的物件物件
- 如何建立和獲取正則物件?物件
- javascript如何建立一個物件例項JavaScript物件
- JVM是如何建立一個物件的?JVM物件
- 如何互動式地建立一個Docker容器Docker
- 多雲已成現實,企業如何更好地實現多雲管理?
- 波卡的國庫機制如何更好地實現Web3.0?Web
- 新能源汽車如何更好地落地供應商夥伴協同系統管理?
- jQuery如何建立一個新的元素物件jQuery物件
- 如何安全地讀寫深度巢狀的物件?巢狀物件
- 人工智慧中的線性代數:如何理解並更好地應用它人工智慧
- 如何讓IT團隊和安全團隊之間更好地進行協作
- 淺談Kotlin語法篇之如何讓函式更好地呼叫(三)Kotlin函式
- 室內導航地圖怎麼做,如何快速建立室內地圖地圖
- MyBatis 的外掛物件如何建立出來的MyBatis物件
- javascript如何建立一個屬性節點物件JavaScript物件
- 物件建立模式物件模式
- JS 建立物件JS物件
- JavaScript建立物件JavaScript物件