2016-12-26 61 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。你把它總結得很好。 –