2016-12-26 35 views
3

这个类有三种方法做同样的事情,他们在等待三秒页面加载,如果在页面加载返回true。
我的问题是,我该如何决定哪一段代码最好?
我知道Lambda is preferred above Anon classes,但为什么是静态嵌套类(pageLoaded3)不好?根据this post它也应该适合。LAMBDA VS匿名VS Static Nested Class和

public final class ExpectedConditions { 

    private ExpectedConditions() { 
    } 

    public static ExpectedCondition<Boolean> pageLoaded1() { 
     return (driver) -> { 
      try { 
       Thread.sleep(3000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      return !((JavascriptExecutor) driver).executeScript("return performance.timing.loadEventEnd", new Object[0]) 
        .equals("0"); 
     }; 
    } 

    public static ExpectedCondition<Boolean> pageLoaded2() { 
     return new ExpectedCondition<Boolean>() { 
      @Override 
      public Boolean apply(WebDriver driver) { 
       try { 
        Thread.sleep(3000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       return !((JavascriptExecutor) driver) 
         .executeScript("return performance.timing.loadEventEnd", new Object[0]).equals("0"); 
      } 
     }; 
    } 

    public static ExpectedCondition<Boolean> pageLoaded3() { 
     return new PageLoaded(); 
    } 

    private static class PageLoaded implements ExpectedCondition<Boolean> { 
     @Override 
     public Boolean apply(WebDriver driver) { 
      try { 
       Thread.sleep(3000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      return !((JavascriptExecutor) driver).executeScript("return performance.timing.loadEventEnd", new Object[0]) 
        .equals("0"); 
     } 
    } 

} 

这是三种方法的返回类型的接口:

public interface ExpectedCondition<T> extends Function<WebDriver, T> {} 
+3

您的三个方法在功能上是等同的(您的代码将执行相同的操作)。是什么让你认为一个静态嵌套类是不合适的? – assylias

+0

_我该如何决定哪一段代码最好?_你能更具体地询问一下你正在寻找什么吗?我对这类问题的一般回答是“最可读的版本”... –

+0

这是我的问题。我知道所有三项工作,但我知道在这种情况下,不应使用匿名课程。在阅读有关成员内部类时,他们还明确地说,当不使用外部类变量时,请使用静态内部类。那么是否有一个规则或惯例也说明应该或不应该使用静态内部类?还是仅仅是偏好? –

回答

1

正如评论已经提到:该功能是等效的。所以在技术上,差别很小。所有的方法都被编译成相似的字节码。因此,只有在代码本身的基础上,才能回答哪一个是“最佳”的问题。在那里,可能会应用不同的标准。

首先,彼得Lawrey的评论所说:你可以拉出Thread.sleep呼叫到一个辅助方法:

private static void pause(long ms) 
{ 
    try 
    { 
     Thread.sleep(ms); 
    } 
    catch (InterruptedException e) 
    { 
     Thread.currentThread().interrupt(); 
    } 
} 

此外,你可以拉出来的是实现有成核心功能helper方法:

private static Boolean execute(WebDriver driver) 
{ 
    pause(3000); 
    return !((JavascriptExecutor) driver) 
     .executeScript("return performance.timing.loadEventEnd", new Object[0]) 
     .equals("0"); 
} 

使用这种方法,给定的方法之间的相似性就更加明显:他们是调用此方法的唯一不同的方式!而且我认为引入这样一种方法会带来额外的好处。该方法是一个清晰的“构建块”,具有清晰的界面(希望清晰的JavaDoc)。

此外,该方法将敞开大门的第四实现 - 即一个使用的方法参考:

public static ExpectedCondition<Boolean> pageLoaded4() 
{ 
    return ExpectedConditions::execute; 
} 

所以,你现在有实现所期望的functionaliy的四种方式:

  1. With a lambda
  2. 使用匿名类
  3. 对于静态肠子类
  4. 随着方法参考

务实角度来说,一个可以争论的优点和缺点:

  • 方法3,用静态肠子类:这是不必要。如果静态内部类只有是方法调用的包装,它不起到真正的目的。它引入了一个新的名字PageLoaded你的情况),并在源代码中一个新的间接 - 这意味着程序员来查找PageLoaded类,看看它做什么。在其他情况下,这可能是另一回事。例如。如果PageLoaded类有其他方法或字段,但在这里不是这种情况。

  • 方法2,用匿名内部类:有人可能会说,对于一个功能界面匿名类只是“老式”或写它的“预Java8路”。如果必须实现的类型是一个功能接口(即具有单一抽象方法),那么使用lambda或方法引用只是更短,更方便,并且没有任何明显的缺点。 (当然,这是不可能的,如果要实现具有类型有多个抽象方法,但再次,这是不是这里的情况。)

  • 方法1,具有拉姆达:这是标准在Java 8中实现这样的功能接口的方式。我个人更喜欢使用lambda体。在你的问题

    return (driver) -> { 
        // "Many" lines of code, maybe even nested, with try-catch blocks 
    }; 
    

    像一个一个lambda是恕我直言没有那么可读性和简洁,我平时尽量保持这些机构尽可能短。在最好的情况下,{括号}可以省略 - 有疑问的是,通过引入包含λ体的方法方法。在这种情况下,人们通常可以将其归结为最后一种方法:

  • 方法4,带有方法参考。这可能有点主观,但我认为这是最可读的。该方法的优点是作为具有明确功能的“构建块”,其可以在JavaDocs中明确指定。此外,您甚至可以考虑省略包装方法(上面称为pageLoaded4),并简单地将方法提供为public。然后,用户,谁原名

    ExpectedCondition<Boolean> condition = 
        ExpectedConditions::pageLoaded4(); 
    

    可能只是使用的方法直接

    ExpectedCondition<Boolean> condition = 
        ExpectedConditions::execute; 
    

    但这取决于确切的应用模式和这个类的预期界面。可能不希望直接公开此方法。

+0

非常好的答案,我很感激它。我的问题是我无法读书,应该或不应该使用静态内部类的方法3。你把它总结得很好。 –