学习重构(5)-简化条件表达式
1.Decompose Conditional (分解条件表达式)
应用场景:你有一个复杂的条件(if-then-else)语句。从if、then、else三个段落中分别提炼出独立函数。
示例:
if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
charge = quantity * mWinterRate + mWinterServiceCharge;
} else {
charge = quantity * mSummerRate;
}
重构为:
if (notSummer(date)) {
charge = winterCharge(quantity);
} else {
charge = summerCharge(quantity);
}
private boolean notSummer(Date date) {
return date.before(SUMMER_START) || date.after(SUMMER_END);
}
private double winterCharge(int quantity) {
return quantity * mWinterRate + mWinterServiceCharge;
}
private double summerCharge(int quantity) {
return quantity * mSummerRate;
}
2.Consolidate Conditional Expression (合并条件表达式)
应用场景:你有一系列条件测试,都得到相同结果。将这些测试合并为一个条件表达式,并将这个条件表达式提炼成一个独立函数。
示例:
double disabilityAmount() {
if(mSeniority < 2) {
return 0;
}
if(mMonthsDisabled > 12) {
return 0;
}
if(mIsPartTime) {
return 0;
}
// compute the disability amount ...
}
重构为:
double disabilityAmount() {
if(isNotEligibleForDisability()) {
return 0;
}
// compute the disability amount ...
}
private boolean isNotEligibleForDisability() {
return (mSeniority < 2) || (mMonthsDisabled > 12) || mIsPartTime;
}
3.Consolodate Duplicate Conditional Fragments (合并重复的条件片段)
应用场景:在条件表达式的每个分支上有着相同的一段代码。将这段重复代码搬移到条件表达式之外。
示例:
if(isSpecialDeal()) {
total = price * 0.95; send();
} else {
total = price * 0.98; send();
}
重构为:
if(isSpecialDeal()) {
total = price * 0.95;
} else {
total = price * 0.98;
}
send();
4.Remove Control Flag (移除控制标记)
应用场景:在一系列布尔表达式中,某个变量带有“控制标记”的作用。以break语句或return语句取代控制标记。
示例:void checkSecurity(String[] people) {
boolean found = false;
for(int i = 0; i < people.length; i++) {
if(!found) {
if(people[i].equals("Don")) {
sendAlert();
found = true;
}
if(people[i].equals("John")) {
sendAlert();
found = true;
} } } }
重构为:void checkSecurity(String[] people) {
for(int i = 0; i < people.length; i++) {
if(people[i].equals("Don")) {
sendAlert();
break;
}
if(people[i].equals("John")) {
sendAlert();
break;
} } }
5.Replace Nested Conditional with Guard Clauses (以卫语句取代嵌套条件表达式)
应用场景:函数中的条件逻辑使人难以看清正常的执行路径。使用卫语句表现所有特殊情况。
条件表达式常有两种表现形式:a)所有分支都属于正常行为;b)表达分支中只有一种是正常行为,其他都是不常见的情况。如果两条分支都是正常行为,就应该使用形如if...else...的条件表达式;如果某个条件极其罕见,就应该单独检查该条件,并在该条件为真时立刻从函数中返回。这样的单独检查常被称为“卫语句”。
示例:
double getPayAmount() {
double result; if(mIsDead) {
result = deadAmount();
} else {
if(mIsSeparated) {
result = separatedAmount();
} else {
if(mIsRetired) {
result = retiredAmount();
} else {
result = normalPayAmount();
} } }
return result;
}
重构为:
double getPayAmount() {
if(mIsDead) {
return deadAmount();
}
if(mIsSeparated) {
return separatedAmount();
}
if(mIsRetired) {
return retiredAmount();
}
return normalPayAmount();
}
6.Replace Conditional with Polymorphism (以多态取代条件表达式)
应用场景:你手上有个条件表达式,它根据对象类型的不同而选择不同的行为。将这个条件表达式的每个分支放进一个子类内的覆写函数中,然后将原始函数声明为抽象函数。
示例:
double getSpeed() {
switch(mType) {
case EUROPEAN: return getBaseSpeed();
case AFRICAN: return getBaseSpeed() - getLoadFactor() * mNumberOfCoconuts;
case NORWEGIAN_BLUE: return mIsNailed ? 0 : getBaseSpeed(mVoltage);
}
throw new RuntimeException("Should be unreachable.");
}
重构为:
abstract class Bird {
abstract double getSpeed();
}
class European extends Bird {
double getSpeed() {
return getBaseSpeed();
} }
class African extends Bird() {
double getSpeed() {
return getBaseSpeed() - getLoadFactor() * mNumberOfCoconuts;
} }
class NorwegianBlue extends Bird {
double getSpeed() {
return mIsNailed ? 0 : getBaseSpeed(mVoltage);
} }
7. Introduce Null Object (引入Null对象)
应用场景:你需要再三检查某对象是否为null,将null值替换为null对象。
示例:
if (custom == null) {
plan = BillingPlan.basic();
} else {
plan = custom.getPlan();
}
重构为:
class Custom {
public Plan getPlan() {
return normalPlan;
}
public boolean isNull() {
return false;
}
}
class NullCustom extends Custom {
public Plan getPlan() {
return BillingPlan.basic();
}
public boolean isNull() {
return true;
}
}
8. Introduce Assertion (引入断言)
应用场景:某一段代码需要对程序状态做出某种假设。以断言明确表现这种假设。