1. 前言
重構老程式碼中遇到了不少類似下面這種寫法:
public void attend(String value) {
if ("0".equals(value)) {
//todo
} else if ("1".equals(value)) {
//todo
} else {
//todo
}
}
腦殼疼!從 Java 語法上無懈可擊,但是從業務上卻讓人無法理解其中 0
和 1
的含義它們統稱為魔法值 。 對於上面的程式碼我們往往需要通過上下文推斷出來邏輯,如果是非常複雜的業務或者10年前的程式碼那就更慘了,搞不好文件也沒有。為了可讀性,所以我們要儘量避免出現魔法值。今天就來講幾種避免魔法值的操作。
2. 避免魔法值的一些操作。
一般魔法值都是不經常變動的。對於魔法值的處理要結合業務和作用域。
2.1 靜態常量
如果該值的作用域在一個類中或者同一個包下,一般可以使用靜態常量來解決。
private static final String FEMALE = "0";
private static final String MALE = "1";
public void attend(String value) {
if (FEMALE.equals(value)) {
//todo
} else if (MALE.equals(value)) {
//todo
} else {
//todo
}
}
這樣是不是清晰了許多,原來 0
和 1
代表的是性別(當然需要配合你良好的變數命名習慣)。
2.2 使用介面
既然我們使用了靜態常量那麼我們可以將魔法值封裝入介面也是可以的。
public interface Gender {
String FEMALE = "0";
String MALE = "1";
}
2.3 使用列舉
但是介面的意義在於提供抽象的功能而不是儲存一些常量值,顯然違背了介面設計的初衷。所以jdk1.5引入了列舉型別 enum
。
public enum GenderEnum {
FEMALE,
MALE
}
很多情況這種寫法就夠用了,你可以通過 GenderEnum.MALE.ordinal()
獲取對應列舉的數字序號,也可以通過GenderEnum.MALE.name()
獲取對應列舉的字串名稱。他們大多數情況下都可以用來進行一些邏輯標識。但是滿足不了我們上面最初的設計,我們需要來改造一下列舉類的建構函式。
public enum GenderEnum {
FEMALE("0"),
MALE("1");
private final String value;
GenderEnum(String value) {
this.value = value;
}
public String value() {
return this.value;
}
}
這樣改寫之後我們就能通過 value()
方法拿到具體的值了。
我們給自己再增加點需求,以達到你的列舉更加友好的可讀性。
public enum GenderEnum {
UNKNOWN("-1", "未知"),
FEMALE("0", "女性"),
MALE("1", "男性");
private final String value;
private final String description;
GenderEnum(String value, String description) {
this.value = value;
this.description = description;
}
public String value() {
return this.value;
}
public String description() {
return this.description;
}
}
description
值不但可以幫助我們知道該列舉的實際代表意義,甚至可以作為一種說明返回給前端業務。
小貼士:列舉儘量不要使用中文宣告,如 FEMALE 直接宣告為 女性。另外列舉是單例的,因此無法使用clone和反序列化。
3. 總結
今天我們瞭解瞭如何優雅處理編碼中的魔法值,特別是列舉方案。希望對你有用。
關注公眾號:Felordcn 獲取更多資訊