2014-03-25 202 views
1

我是一名初學者,講師告訴我要減少這兩個函數中的重複代碼。這是一個圖書館。我想我需要一個更多的方法來檢查數組。我需要的是我需要使用的一些建議/原則。我會自己寫這個方法。謝謝! getBooks()返回存儲書籍的ArrayList。需要幫助減少重複代碼

public List<Book> getAvailableBooks() { 
    List<Book> result = new ArrayList<Book>(); 
    for (int i = 0; i < this.getBooks().size(); i++) { 
     if (this.getBooks().get(i).getPerson() == null) { 
      result.add(this.getBooks().get(i)); 
     } 
    } 
    return result; 
} 

public List<Book> getUnavailableBooks() { 
    List<Book> result = new ArrayList<Book>(); 
    for (int i = 0; i < this.getBooks().size(); i++) { 
     if (this.getBooks().get(i).getPerson() != null) { 
      result.add(this.getBooks().get(i)); 
     } 
    } 
    return result; 
} 
+0

謝謝你的答覆。我真笨。這樣一個簡單的答案:) – user2879175

回答

1

傳遞一個布爾型參數,應說明什麼

(this.getBooks().get(i).getPerson() == null) 

應求,並添加一個條件檢查。即如果這個表達式返回true或false。

2

您已經有兩種方法。你不能通過增加一個來減少。

但是你可以有一種方法而不是兩種。例如

public List<Book> getBooks(boolean available) { 

現在你有一種方法,你可以告訴它,你是否想要可用或不可用的書。

+0

使用'boolean'類型來表示可用性不是一個好主意。誰知道'getBooks(true)'會給你什麼? –

+0

@RohitJain:這是一個很好的觀點,我曾考慮過這個問題。但是沒有把它放在那裏,因爲我認爲它可能會將焦點從問題的主要觀點轉移。 –

1

我這裏還有一些建議:

  • 使用加強for循環,而不是索引之一。這將避免在每種方法中使用兩次this.getBooks().get(i)

  • 不可獲得的書籍+可供借閱的書= Total books。使用這個公式可以避免在這兩種方法中編寫所有的代碼。您可能需要使用Set<Book>而不是List<Book>,以使其更易於使用。 [建議:設置差異]。

  • 此外,而不是做那些方法中null檢查,我會如果可用,否則false只添加Book類中的方法isAvailable(),這將返回true

+0

+1偉大的建議! –

1

在一般情況下,如果你看到一個很常見的模式在你的代碼重複,經常是爲了減少重複的機會。第一步是查看您的代碼並確定實際差異。您有:

public List<Book> getAvailableBooks() { 
    List<Book> result = new ArrayList<Book>(); 
    for (int i = 0; i < this.getBooks().size(); i++) { 
     if (this.getBooks().get(i).getPerson() == null) { 
      result.add(this.getBooks().get(i)); 
     } 
    } 
    return result; 
} 

public List<Book> getUnavailableBooks() { 
    List<Book> result = new ArrayList<Book>(); 
    for (int i = 0; i < this.getBooks().size(); i++) { 
     if (this.getBooks().get(i).getPerson() != null) { 
      result.add(this.getBooks().get(i)); 
     } 
    } 
    return result; 
} 

忽略方法名稱,讓我們進行逐行比較。這樣,我們就可以看出其中的區別:

if (this.getBooks().get(i).getPerson() == null) { 
// vs: 
if (this.getBooks().get(i).getPerson() != null) { 

==!=唯一的區別;條件反轉。在確定差異之後,下一步是查看是否可以對行爲進行參數化,以使邏輯本身完全相同,並且僅取決於少數外部變量的值。在這種情況下,我們可以看到這樣的轉變:

a == x => (a == x) == true 
a != x => (a == x) == false 
both:  => (a == x) == <variable> 

因此,我們可以使這兩條線相當於:

boolean available = true; 
if ((this.getBooks().get(i).getPerson() == null) == available) { 
// vs: 
boolean available = false; 
if ((this.getBooks().get(i).getPerson() == null) == available) { 

現在的邏輯是等價的,我們可以通過簡單地在兩者之間選擇改變available。做一個方法參數,瞧!

public List<Book> getBooksByAvailability (bool available) { 
    List<Book> result = new ArrayList<Book>(); 
    for (int i = 0; i < this.getBooks().size(); i++) { 
     if ((this.getBooks().get(i).getPerson() == null) == available) { 
      result.add(this.getBooks().get(i)); 
     } 
    } 
    return result; 
} 

需要注意的是另一種方式來處理這個問題是使「可用性」本身是一本書的一個屬性。例如,如果您移動可用性測試到一個新的方法Book.isAvailable(),溶液變得有點更加明顯:

public List<Book> getBooksByAvailability (bool available) { 
    List<Book> result = new ArrayList<Book>(); 
    for (int i = 0; i < this.getBooks().size(); i++) { 
     if (this.getBooks().get(i).isAvailable() == available) { 
      result.add(this.getBooks().get(i)); 
     } 
    } 
    return result; 
} 

,並且具有讓你改變「庫存狀況」的內部定義,而無需修改代碼的好處其他地方(例如,如果您將來決定getPerson() == null不足以表示「可用性」,則只需在Book.isAvailable()中更改)。

至於清晰,你可以作爲羅希特耆那教的this answer提到,切換到加強for循環來提高可讀性有點,例如:

public List<Book> getBooksByAvailability (bool available) { 
    List<Book> result = new ArrayList<Book>(); 
    for (Book book : this.getBooks()) { 
     if (book.isAvailable() == available) { 
      result.add(book); 
     } 
    } 
    return result; 
} 

爲了讓您的兩個現有的功能,如果這是必要的,你可以使用類似上述的東西作爲私人效用方法,由兩個公共方法調用。

+0

這是可怕的重構方式,我會說。當然,看起來並不乾淨,而且首先了解「if」情況也有點棘手。 –

+0

@RohitJain我不知道這是否是一種可怕的重構方式,但我認爲最初的代碼很奇怪。我剛剛進行了編輯,在您發表評論的同時,在「Book」中添加了有關將「可用性」移動到其中的評論。這種方法最終會帶來令人爭議的更清晰的結果。 –

+0

@RohitJain哦,是的,你的答案中的一切都是很好的建議。我不想在這裏包含太多;只需進行極少的更改即可從現有代碼中刪除重複代碼。目標是一般的「如何發現並刪除重複的代碼」。 –

0

如果你不想改變方法簽名,我認爲你不能做得比你已經有的更好。您可以重寫循環來進行foreach,並且可能會執行列表的替換。骯髒的解決方案,但講師可能會採取。

public List<Book> getAvailableBooks() { 
    Set<Book> result = new HashSet<>(getBooks()); 
    result.removeAll(getUnavailableBooks()); 
    return new ArrayList<Book>(result); 
} 

public List<Book> getUnavailableBooks() { 
    List<Book> result = new ArrayList<Book>(); 
    for (Book b: getBooks()) { 
     if (b.getPerson() != null) { 
      result.add(b); 
     } 
    } 
    return result; 
} 

也許不是最快的解決方案,但很短