概述
1、DecomposeConditional(分解条件表达式)
动机:你有一个复杂的条件(if-then-else)语句。
做法:从if、then、else三个段落中分别提炼出独立函数。
代码1:
if(date.before(SUMMER_START)||date.after(SUMMER_END))
charge=quantity*_winterRate+_winterServiceCharge;
elsecharge=quantity*_summerRate;
代码2:date.before、date.after在什么时间之前,在什么时间之后
if(notSummer(date))
charge=winterCharge(quantity);
elsecharge=summerCharge(quantity);
privatebooleannotSummer(Datedate){
returndate.before(SUMMER_START)||date.after(SUMMER_END);
}
privatedoublesummerCharge(intquantity){
returnquantity*_summerRate;
}
privatedoublewinterCharge(intquantity){
returnquantity*_winterRate+winterServiceCharge;
}
2、ConsolidateConditionalExpression(合并条件表达式)
代码1:
doubledisabilityAmout(){
if(_seniority<2)return0;
if(_monthsDisabled>12)return0;
if(_isPartTime)return0;
}
代码2:
doubledisabilityAmout(){
if(isNotEligibleForDisability())return0;
}
booleanisNotEligibleForDisability(){
return((_seniority<2)||(_monthsDisabled>12)||(_isPartTime));
}
3、ConsolidateDuplicateConditionalFragments(合并重复的条件片段)
代码1:
if(isSpecialDeal()){
total=price*0.95;
send();
}
else{
total=price*0.98;
send();
}
代码2:
if(isSpecialDeal())
total=price*0.95;
else
total=price*0.98;
send();
4、RemoveControlFlag(移除控制标记)
做法:以break语句或者return语句取代控制标记。
代码1:
voidcheckSeurity(String[]people){
booleanfound=false;
for(inti=0;i<people.length;i++){
if(!found){
if(people[i].equals("Don")){
sendAlert();
found=true;
}
if(people[i].equals("John")){
sendAlert();
found=true;
}
}
}
}
代码2:
voidcheckSeurity(String[]people){
booleanfound=false;
for(inti=0;i<people.length;i++){
if(people[i].equals("Don")){
sendAlert();
break;
}
if(people[i].equals("John")){
sendAlert();
break;
}
}
}
代码3:
voidcheckSeurity(String[]people){
Stringfound="";
for(inti=0;i<people.length;i++){
if(found.equals("")){
if(people[i].equals("Don")){
sendAlert();
found="Don";
}
if(people[i].equals("John")){
sendAlert();
found="John";
}
}
}
}
代码4:
voidcheckSeurity(String[]people){
for(inti=0;i<people.length;i++){
if(people[i].equals("Don")){
sendAlert();
return"Don";
}
if(people[i].equals("John")){
sendAlert();
return"John";
}
}
}
5、ReplaceNestedConditionalwithGuardClauses(以卫语句取代嵌套条件表达式)
动机:函数中的条件逻辑使人难以看清正常的执行路径。
代码1:
doublegetPayAmount(){
doubleresult;
if(_isDead)result=deadAmount();
else{
if(_isSeparated)result=separatedAmount();
else{
if(_isRetired)result=retiredAmount();
elseresult=normalPayAmount();
}
}
returnresult;
}
代码2:
doublegetPayAmount(){
if(_isDead)returndeadAmount();
if(_isSeparated)returnseparatedAmount();
if(_isRetired)returnretiredAmount();
returnnormalPayAmount();
}
6、ReplaceConditionalwithPolymorphism(以多态取代条件表达式)
动机:你手上有个条件表达式,它根据对象类型的不同而选择不同的行为。
做法:将这个条件表达式的每个分支放进一个子类内的覆写函数中,然后将原始函数声明为抽象函数
代码1:
classEmployee..
doublegetSpeed(){
switch(_type){
caseEUROPEAN:
returngetBaseSpeed();
caseAFRICAN:
returngetBaseSpeed()-getLoadFactor()*_numberOfCoconuts;
caseNORWEGIAN_BLUE:
return(_isNailed)?0:getBaseSpeed(_voitage);
}
thrownewRuntimeException("Shouldbeunreachable");
}
代码2:
classEmployeeType...
abstractdoublegetSpeed();
classEngineer...
doublegetSpeed(){
returngetBaseSpeed)();
}
classSaleman...
doublegetSpeed(){
returngetBaseSpeed()-getLoadFactor()*_numberOfCoconuts;
}
classManager...
doublegetSpeed(){
return(_isNailed)?0:getBaseSpeed(_voitage);
}
7、IntroduceNullObject(引入Null对象)
动机:你需要再三检查对象是否为Null。
代码1:if(customer==null)plan=billingPlan.basic();
elseplan=customer.getPlan();
代码2:
classNullCustomerextendsCustomer{
publicbooleanisNull(){
returntrue;
}
}
classCustomer..
publicbooleanisNull(){
returnfalse;
}
如果你喜欢,也可以新建一个借口,昭告大家“这里使用了空对象”;
interfaceNullable{
booleanisNull();
}
classCustomerimplementsNullable
我还喜欢加入一个工厂函数,专门用来创建NullCutomer对象。这样一来,用户就不必知道空对象的存在了:
classCustomer...
staticCustomernewNull(){
returnnewNullCustomer();
}
示例:
classSite...
CustomergetCustomer(){
return(_customer==null)?Customer.newNull():_customer;
}
Customercustomer=site.getCustomer();
BillingPlanplan;
if(customer.isNull())plan=BillingPlan.basic();
elseplan=customer.getPlan();
8、IntroduceAssertion(引入断言)
动机:某一段代码需要对程序状态做出某种假设。
做法:以断言明确表现这种假设
代码1:doublegetExpenseLimit(){
//shouldhaveeitherexpenselimitorprimaryproject
return(_expenseLimit!=NULL_EXPENSE)?_expenseLimit;
_primaryProject.getMemberExpenseLimit();
}
代码2:doublegetExpenseLimit(){
Assert.isTrue(_expenseLimit!=NULL_EXPENSE||_primaryProject!=null);
return(_expenseLimit!=NULL_EXPENSE)?
_expenseLimit:
_primaryProject.getMemberExpenseLimit();
}
断言是一个条件表示,应该总是为真。如果它失败,表示程序员犯了错误,因此断言的失败应该导致一个非受控异常(uncheckedexception)。断言绝对不能被系统的其他部分使用。实际上,程序最后的成品往往将断言统统删除。因此,标记“某些东西是个断言”是很重要的。
断言可以作为交流与调试的铺助。在交流的角度上,断言可以帮助程序阅读者理解代码所做的假设:在调试的角度上,断言可以再距离bug最近的地方抓住它们。
编写一个辅助类(例如Assert类)当然有所帮助,可惜的是断言参数中的任何表达式不论什么情况都一定会被执行一遍。阻止它的唯一方法就是使用类似下面的手法:
doublegetExpenseLimit(){
Assert.isTrue(Assert.ON&&(_expenseLimit!=NULL_EXPENSE||_primaryProject!=null));
return(_expenseLimit!=NULL_EXPENSE)?
_expenseLimit:
_primaryProject.getMemberExpenseLimit();
如果Assert.ON是个常量,编译器就会对它进行检查;如果它等于false,就不再执行条件表达式后半段代码。
最后
以上就是凶狠电灯胆为你收集整理的重构改善既有代码的设计--简化条件表达式的全部内容,希望文章能够帮你解决重构改善既有代码的设计--简化条件表达式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复