重複代碼---提煉函數(Extract method)

一、Extract Method:提煉方法java

將有些代碼單獨提取出來放入到一個獨立的函數中,並讓函數名稱來解釋該函數的用途。函數

 

[java]  view plain  copy
 
  1. public void printOwing(double amount) {  
  2.     printBanner();  
  3.     System.out.println("name:" + name);  
  4.     System.out.println("amount:" + amount);  
  5. }  

能夠寫成:測試

 

 

[java]  view plain  copy
 
  1. public void printOwing(double amount) {  
  2.     printBanner();  
  3.     printDetails(amount);  
  4. }  
  5.   
  6. /** 
  7.  * 描述:打印詳情 
  8.  */  
  9. public void printDetails(double amount) {  
  10.     System.out.println("name:" + name);  
  11.     System.out.println("amount:" + amount);  
  12. }  

當看到一個過長的函數或須要註釋才能讓人理解的代碼,應該考慮將這段代碼放到一個單獨的獨立函數中。spa

 

作法:.net

一、建立一個新的函數,根據函數的意圖來命名。blog

二、將提煉出來的代碼從源函數(source)中拷貝到目標函數(target)中。element

三、仔細檢查提煉出來的代碼,看其中是否引用了做用域僅限於源函數的變量。作用域

四、檢查是否有僅限於被提煉碼的臨時變量,若是有,在目標函數中將它申明爲局部變量。get

五、檢查提煉碼,看是否有任何局部變量的值被改變,若是有一個臨時變量的值被改變,看是否可以將提煉碼處理爲一個查詢,並將結果賦值給臨時變量。it

六、被提煉碼中須要讀取的局部變量,經過參數傳遞給目標函數。

七、處理完全部局部變量後編譯,在源函數中替換目標函數,測試。

例子:

 

[java]  view plain  copy
 
  1. private String name;  
  2. private Vector<Order> orders = new Vector<Order>();  
  3.   
  4. public void printOwing() {  
  5.     Enumeration env = orders.elements();  
  6.     double totalAmount = 0.0;  
  7.     System.out.println("****************");  
  8.     System.out.println("***** test *****");  
  9.     System.out.println("****************");  
  10.   
  11.     while (env.hasMoreElements()) {  
  12.         Order order = (Order) env.nextElement();  
  13.         totalAmount += order.getAmout();  
  14.     }  
  15.   
  16.     System.out.println("name:" + name);  
  17.     System.out.println("amount:" + totalAmount);  
  18. }  

提取沒有局部變量的函數:

 

 

[java]  view plain  copy
 
  1. private void printBanner() {  
  2.     System.out.println("****************");  
  3.     System.out.println("***** test *****");  
  4.     System.out.println("****************");  
  5. }  

提取有局部變量的函數:

 

若是被提煉碼只是須要讀取這些變量的值,並不修改他們,這時候咱們只須要將它做爲一個參數傳遞給目標函數便可,例:

 

[java]  view plain  copy
 
  1. public void printDetails(double amount) {  
  2.     System.out.println("name:" + name);  
  3.     System.out.println("amount:" + amount);  
  4. }  

若是被提煉碼對局部變量進行賦值:

 

一、這個變量只是在提煉碼區域中使用,那麼能夠將這個臨時變量的申明式移動到提煉碼中,而後一塊兒提煉出去。

二、若是被提煉碼以外的代碼也使用了這個變量,可分爲:

     1)、若是這個變量在被提煉碼以後未再被使用,只須要在目標函數中修改它的值便可。

     2)、若是在提煉碼以後還要使用該變量,這個時候就須要讓目標函數返回該變量改變後的值。

一、提取getTotalAmount():

 

[java]  view plain  copy
 
  1. /** 
  2.  * 描述:獲取總帳戶餘額 
  3.  */  
  4. public double getTotalAmount() {  
  5.     double totalAmount = 0.0;  
  6.     Enumeration env = orders.elements();  
  7.     while (env.hasMoreElements()) {  
  8.         Order order = (Order) env.nextElement();  
  9.         totalAmount += order.getAmount();  
  10.     }  
  11.     return totalAmount;  
  12. }  

這個時候的getOwing()可寫成:

 

 

[java]  view plain  copy
 
  1. public void printOwing() {  
  2.     printBanner();  
  3.     double totalAmount = getTotalAmount();  
  4.     printDetails(totalAmount);  
  5. }  

這裏若是totalAmount初始值不是0,而有一個初值,這個時候就須要將這個初值傳入到目標函數中去。

 

[java]  view plain  copy
 
  1. public void printOwing(double initAmount) {  
  2.     printBanner();  
  3.     double totalAmount = initAmount * 1.5;  
  4.     totalAmount = getTotalAmount(totalAmount);  
  5.     printDetails(totalAmount);  
  6. }  
  7.   
  8. /** 
  9.  * 描述:獲取總帳戶餘額 
  10.  */  
  11. public double getTotalAmount(double initAmount) {  
  12.     double totalAmount = initAmount;  
  13.     Enumeration env = orders.elements();  
  14.     while (env.hasMoreElements()) {  
  15.         Order order = (Order) env.nextElement();  
  16.         totalAmount += order.getAmount();  
  17.     }  
  18.     return totalAmount;  
  19. }  

臨時變量每每不少,這個時候能夠考慮Replace Temp with Query(以查詢方法替代臨時變量),若是這樣依舊困難,能夠考慮Replace method with method object(以函數變量替換函數)。

相關文章
相關標籤/搜索