9.1分解条件式•复杂的条件语句•从if、then、else三个段落中分别提炼出独立函数。if(date.before(SUMMER_START)||date.after(SUMMER_END))charge=quantity*_winterRate+_winterServiceCharge;elsechareg=quantity*_summerRate;if(notSummer(data))charge=winterCharge(quantity);elsecharge=summerCharge(quantity);假设要计算购买某样商品的总价(总价=数量×单价〕,而这个商品在冬季和夏季的单价是不同的:把每个分支的判断条件都提炼到一个独立函数中,如下所示:if(date.before(SUMMER_START)||date.after(SUMMER_END))charge=quantity*_winterRate+_winterServiceCharge;elsechareg=quantity*_summerRate;if(notSummer(date))charge=winterCharge(quantity);elsechareg=summerCharge(quantity);privatebooleannotSummer(Datedate){returndate.before(SUMMER_START)||date.after(SUMMER_END);}privatedoublesummerCharge(intquantity){returnquantity*_summerRate;}privatedoublewinterCharge(intquantity){returnquantity*_winterRate+_winterServiceCharge;}9.2合并条件式•一系列条件测试,都得到相同结果•将这些测试合并为一个条件式,并将这个条件式提炼成为一个独立函数。doubledisablityAmount(){if(_seniority2)return0;if(_monthsDisabled12)return0;if(_isPartTime)return0;}doubledisabilityAmount(){if(ifNotBligableForDisablility())return0;}1.确定这些条件语句都没有连带影响。2.使用适当的逻辑操作符,将一系列相关条件式合并为一个。3.编译,测试。4.对合并后的条件式提炼函数。连续的的条件检查,等价于一个以逻辑OR连接起来的语句:doubledisablityAmount(){if(_seniority2)return0;if(_monthsDisabled12)return0;if(_isPartTime)return0;}doubledisablityAmount(){if(_seniority2)||(_monthsDisabled12)||(_isPartTime)return0;}然后,在新条件式中提炼出一个独立函数,以函数名称表达该语句所检查的条件doubledisabilityAmount(){if(ifNotBligableForDisablility())return0;}BoolenifNotBligableForDisablility(){return((_seniority2)||(_monthsDisabled12)||(_isPartTime));}9.3合并重复的条件片段•在条件式的每个分支上有相同的一段代码。•将这段代码搬移到条件式之外。1.找出执行方式不随条件变化而变化的代码:2.如果这些代码位于条件式起始处,就将它移到条件式之前3.如果这些代码位于条件式尾端,就将它移到条件式之后。4.如果这些代码位于条件式中段,需要观察共同代码之前或之后的代码是否改变其他代码。如果有所改变,应该首先将共同代码向前或向后移动,移至条件式的起始处或尾端,再以前面所说的办法来处理。5.如果代码不止一条语句,将共同代码提炼到独立函数中,再以上述方法处理。由于条件式的两个分支都执行了send()函数,所以将该部分代码移到条件式的外围:if(isSpecialDeal()){total=price*0.95;send();}else{total=price*0.98;send();}if(isSpecialDeal())total=price*0.95;elsetotal=price*0.98;send();9.4移除控制标记•在布尔表达式中,某个变量待遇控制标记的作用•以break语句或return语句取代控制标记方法:1.找出跳出这段逻辑的控制标记值。2.用break或continue代替不符合条件式的值赋予标记变量的语句。3.每次并换后,编译并测试。例:以break取代控制标记下列函数用来检杳多个人名之中是否包含两个可疑人物的名字voidcheckSecurity(String[]people){booleanfound=false;for(!found){if(people[i].equals(don)){sendAlert();found=ture;}if(people[i].equals(john)){sendAlert();found=ture;}}}很容易找出控制标记,当变量found被赋予true时,搜索就结束。为此逐一引入break语句:voidcheckSecurity(String[]people){booleanfound=false;for(!found){if(people[i].equals(don)){sendAlert();break;}if(people[i].equals(john)){sendAlert();break;}}}然后把对控制标记的所有引用都去掉voidcheckSecurity(String[]people){for(inti=0;ipeople.length;i++){if(people[i].equals(don)){sendAlert();break;}if(people[i].equals(john)){sendAlert();found=ture;}}}例:以return取代控制标记本项重构的另一种方法是使用return语句。把前面的例子稍加修改,以控制标记记录搜索结果:变量found既是控制标记,也是运算结果。先把计算found变量的代码提炼到一个独立函数中:voidcheckSecurity(String[]people){Stringfound=;for(inti=0;ipeople.length;i++){if(found.equals()){if(people[i].equals(don)){sendAlert();found=don;}}if(people[i].equals(john)){sendAlert();found=john;}}}someLaterCode(found);}voidcheckSecurity(String[]people){Stringfound=foundMiscreant(people);someLaterCode(found);}StringfoundMiscreant(String[]people){Stringfoud=;for(inti=0;ipeople.length;i++){if(found.equals()){if(people[i].equals(don)){sendAlert();found=don;}if(people[i].equals(john)){sendAlert();found=john;}}}returnfound;}然后以return语句取代控制标记StringfoundMiscreant(String[]people){Stringfoud=;for(inti=0;ipeople.length;i++){if(found.equals()){if(people[i].equals(don)){sendAlert();returndon;}if(people[i].equals(john)){sendAlert();returnjohn;}}}returnfound;}最后完全去掉控制标记StringfoundMiscreant(String[]people){for(inti=0;ipeople.length;i++){if(people[i].equals(don)){sendAlert();returndon;}if(people[i].equals(john)){sendAlert();returnjohn;}}return;}9.5以卫语句取代嵌套条件式•函数中的条件逻辑使人难以看清正常的执行路径•以卫语句表现所有特殊情况如果两条分支都是正常行为,应该使用形如if..else..的条件式。如果某个条件极其罕见,应该单独检查该条件,并在该条件为真时立刻从函数中返回。这样的单独检查常常被称为卫语句。方法1.对于每个检查,放进一个卫语句。2.每次将条件捡查替换成卫语句后,编译并测试。例:薪册系统,其中以特殊规则处理死亡员工、驻外员仁、退休员工的薪资。这些情沉不常有,但的确会偶而出现doublegetPayAmount(){doubleresult;if(_isDead)result=deadAmout();else{if(_isSeparated)result=separatedAmount();else{if(_isRetired)result=retiredAmount();elseresult=normalPayAmount();};}returnresult;}doublegetPayAmount(){if(_isDead)returndeadAmout();if(_isSeparated)returnseparatedAmount();if(_isRetired)returnretiredAmount();returnnormalPayAmount();}例:将条件逆反publicdoublegetAdjustedCapital(){doubleresult=0.0;if(_capital0.0){if(_intRate0.0&&_duration0.0){result=(_income/_duration)*ADJ_FACTOR;}}returnresult;}需逐一替换。在插入卫语句前,将相应的条件逆反过来。publicdoublegetAdjustedCapital(){doubleresult=0.0;if(_capital0.0)returnresult;if(_intRate0.0&&_duration0.0)result=(_income/_duration)*ADJ_FACTOR;returnresult;}下一个条件稍复杂,分两步进行。首先加入“logical—NOT”操作publicdoublegetAdjustedCapital(){doubleresult=0.0;if(_capital0.0)returnresult;if(!(_intRate0.0&&_duration0.0))returnresult;result=(_income/_duration)*ADJ_FACTOR;returnresult;}继续简化如下:publicdoublegetAdjustedCapital(){doubleresult=0.0;if(_capital0.0)returnresult;if(_intRate=0.0||_duration=0.0)returnresult;result=(_income/_durati