Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么';在检查条件时,消除代码中嵌套ifs的最佳方法是什么?_Java_Design Patterns_Blackberry - Fatal编程技术网

Java 什么';在检查条件时,消除代码中嵌套ifs的最佳方法是什么?

Java 什么';在检查条件时,消除代码中嵌套ifs的最佳方法是什么?,java,design-patterns,blackberry,Java,Design Patterns,Blackberry,我正在用Java开发一个BlackBerry应用程序,我有一个选项类,其中存储了所有用户设置。问题是我需要检查一些情况,以便知道如何反应。随着我不断添加更多的功能,更多的GUI选项显示给用户,更多的设置存储在options类中,需要检查更多的条件 以以下代码为例: private void doCallMonitoring(int callId){ /*This is the part that I want to avoid. Having multiple nested

我正在用Java开发一个BlackBerry应用程序,我有一个选项类,其中存储了所有用户设置。问题是我需要检查一些情况,以便知道如何反应。随着我不断添加更多的功能,更多的GUI选项显示给用户,更多的设置存储在options类中,需要检查更多的条件

以以下代码为例:

private void doCallMonitoring(int callId){
    /*This is the part that I want to avoid. Having
      multiple nested ifs. Here's just two conditions
      but as I add more, it will get unmantainable
      very quickly.*/
    if(Options.isActive().booleanValue()){
        callTime = new Timer();
        TimerTask callTimeTask = new TimerTask(){
            public void run(){
                callTimeSeconds++;
        if((callTimeSeconds == Options.getSoftLimit().intValue()) && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)){
                    injectDTMFTone(Phone.getActiveCall());
        }else if((callTimeSeconds >= Options.getHardLimit().intValue()) && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)){
                    injectEndCall();
                }
             }
        };     
        callTime.schedule(callTimeTask, 0,1000);
    }else{
    System.out.println("Service not active");
    }
}
我希望它如何工作,就是通过一次电话来验证所有选项,并从中确定行动的诅咒。如何实现这样的设计?

您可以使用“提取方法”重构,并将所有这些检查设置为一个“可读”条件

请看,这一点有点冗长,但关键是要替换如下结构:

       }else if((callTimeSeconds >= Options.getHardLimit().intValue()) && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)){
                injectEndCall();
            }
         }
       ....
       }else if(shouldInjectEndCall() ){
                injectEndCall();
            }
         }
       ...
abstract class Validation { 

      public boolean suceed();
      public void takeAction();
}

class InjectDTMFToneValidation extends Validation { 
    public boolean suceed() { 
        return (callTimeSeconds == Options.getSoftLimit().intValue()) 
               && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)
     }
     public void takeAction() { 
         injectDTMFTone(Phone.getActiveCall());
     }
}

class InjectEndCallValidation extends Validation { 
    public boolean suceed() { 
        return (callTimeSeconds >= Options.getHardLimit().intValue()) 
                && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)
     }
     public void takeAction() { 
         injectEndCall();
     }
}
对于这样的事情:

       }else if((callTimeSeconds >= Options.getHardLimit().intValue()) && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)){
                injectEndCall();
            }
         }
       ....
       }else if(shouldInjectEndCall() ){
                injectEndCall();
            }
         }
       ...
abstract class Validation { 

      public boolean suceed();
      public void takeAction();
}

class InjectDTMFToneValidation extends Validation { 
    public boolean suceed() { 
        return (callTimeSeconds == Options.getSoftLimit().intValue()) 
               && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)
     }
     public void takeAction() { 
         injectDTMFTone(Phone.getActiveCall());
     }
}

class InjectEndCallValidation extends Validation { 
    public boolean suceed() { 
        return (callTimeSeconds >= Options.getHardLimit().intValue()) 
                && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)
     }
     public void takeAction() { 
         injectEndCall();
     }
}

请记住,对象确实具有状态,并且可以使用其他对象来帮助它们完成其工作

另一种选择是执行某种“用多态性替换条件”

尽管看起来只是编写更多的代码,但您可以用“validator”对象替换所有这些规则,并将所有验证都放在某个数组中并循环执行

类似于这个临时代码

  private void doCallMonitoring(int callId){
     // Iterate the valiators and take action if needed. 

      for( Validation validation : validationRules ) { 
          if( validation.succeed() ) { 
              validation.takeAction();
          }
      }
   }
您可以这样实现它们:

       }else if((callTimeSeconds >= Options.getHardLimit().intValue()) && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)){
                injectEndCall();
            }
         }
       ....
       }else if(shouldInjectEndCall() ){
                injectEndCall();
            }
         }
       ...
abstract class Validation { 

      public boolean suceed();
      public void takeAction();
}

class InjectDTMFToneValidation extends Validation { 
    public boolean suceed() { 
        return (callTimeSeconds == Options.getSoftLimit().intValue()) 
               && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)
     }
     public void takeAction() { 
         injectDTMFTone(Phone.getActiveCall());
     }
}

class InjectEndCallValidation extends Validation { 
    public boolean suceed() { 
        return (callTimeSeconds >= Options.getHardLimit().intValue()) 
                && (Phone.getActiveCall().getStatus() == PhoneCall.STATUS_CONNECTED)
     }
     public void takeAction() { 
         injectEndCall();
     }
}
最后在列表中安装它们:

private List<Validation> validationRules = new ArrayList<Validation>();{
   validationrules.add( new InjectDTMFToneValidation() );
   validationrules.add( new InjectEndCallValidation () );
   ...
   ...
}
private List validationRules=new ArrayList();{
添加(新的InjectDTMFToneValidation());
add(newinjectEndCallValidation());
...
...
}
这里的想法是将逻辑转移到子类。当然,你会得到一个更好的结构,也许suceed和takeAction可以被其他更有意义的方法所取代,目的是将验证从原来的地方拉出来

它变得更抽象了。。对


顺便说一句,我为什么要使用选项和Phone类调用它们的静态方法而不是使用实例?

另一个选项是让
injectDMTFTone()
等方法检查它们是否要处理该条件,并根据是否处理该条件返回true或false

例如:

public void run() {
    callTimeSeconds++;
    do {
        if (handleInjectDMTFTone())
            break;
        if (handleInjectEndCall())
            break;
    } while(false);

    callTime.schedule(callTimeTask, 0,1000);
}

boolean handleInjectDMTFTone() {
    if ((callTimeSeconds != Options.getSoftLimit().intValue()) ||
        (Phone.getActiveCall().getStatus() != PhoneCall.STATUS_CONNECTED))
        return false;

    injectDTMFTone(Phone.getActiveCall());
    return true;
}

boolean handleInjectEndCall() {

    if ((callTimeSeconds < Options.getHardLimit().intValue()) ||
        (Phone.getActiveCall().getStatus() != PhoneCall.STATUS_CONNECTED))
        return false;

    injectEndCall();
    return true;
}
public void run(){
callTimeSeconds++;
做{
if(handleInjectDMTFTone())
打破
if(handleInjectEndCall())
打破
}while(假);
callTime.schedule(callTimeTask,01000);
}
布尔handleInjectDMTFTone(){
if((callTimeSeconds!=Options.getSoftLimit().intValue())||
(Phone.getActiveCall().getStatus()!=PhoneCall.STATUS\u CONNECTED))
返回false;
injectDTMFTone(Phone.getActiveCall());
返回true;
}
布尔handleInjectEndCall(){
if((callTimeSeconds
当然,与调用另一个
injectDMTFTone()
方法或
injectEndCall()
方法不同,您只需将该逻辑直接内联到这些方法中。通过这种方式,您将如何以及何时在同一位置处理这些情况的所有逻辑组合在一起

这是我最喜欢的模式之一;使用
if
语句尽可能靠近方法顶部,以消除条件并返回。该方法的其余部分没有缩进很多级别,并且易于阅读


您可以通过创建所有实现相同接口且位于处理程序存储库中的对象来进一步扩展此功能,您的
run
方法可以迭代这些处理程序,以查看哪个将处理它。这对你的情况来说可能是过分的,也可能不是过分的。

所有这些答案可能都是更好的答案。就这一次,我要找一个又快又脏的答案

我非常喜欢通过反转复杂的嵌套IF来简化它们

if(!Options.isActive().booleanValue()) {
    System.out.println("Service not active");
    return;
}
the rest...
我知道有些人不喜欢mid方法返回,但当您验证对我来说一直是一个很棒的模式的输入条件时,我从不后悔使用它

它确实简化了方法的外观


如果您编写的方法比屏幕长,请不要这样做,也不要写一条大注释指出它——很容易丢失return语句而忘记您所做的。更好的是,不要编写比屏幕更长的方法。

我建议您购买Martin Fowler的《重构》一书:这是一本必备书。谢谢您的推荐。Phone是RIMs JDE提供的一个类,它由静态方法组成,用于控制BlackBerry使用的Phone应用程序。选项类用于永久存储所述选项,而不是过度使用。它看起来既有趣又简单。我要试一试。