2011-12-23 59 views
1

如果我想驗證我的輸入,我應該將驗證代碼作爲私有幫助器方法還是創建單獨的靜態幫助器類?驗證代碼是否增加了對象的大小?在Java中創建輸入驗證方法的好習慣?

更多信息

比方說,我有一個類

import java.util.Vector; 


public class Place { 
    private final double longitude; 
    private final double latitude; 
    private final String id; 

    private  String   address; 
    private  String   name; 
    private  String   types; 
    private  String   icon; 
    private  String   phoneNumber; 
    private  String   websiteUrl; 
    private  int    rating; 
    private  Vector<Integer> challenges; 

    public static class Builder { 
     // required parameter 
     private final double longitude; 
     private final double latitude; 
     private final String id; 
     // optional parameter 
     private  String   address = "n/a"; 
     private  String   name = "n/a"; 
     private  String   icon = "n/a"; 
     private  String   phoneNumber = "n/a"; 
     private  String   websiteUrl = "n/a"; 
     private  String   types = "n/a"; 
     private  Vector<Integer> challenges = new Vector<Integer>(); 
     private  int    rating = 0; 

     public Builder(double longitude, double latitude, String id) { 
      assert(longitude >= -180.0 && longitude <= 180.0); 
      assert(latitude >= -90.0 && longitude <= 90.0); 
      this.longitude = longitude; 
      this.latitude = latitude; 
      this.id = id; 
     } 

     public Builder address(String address) { 
      this.address = address; 
      return this; 
     } 

     public Builder types(String types) { 
      this.types = types; 
      return this; 
     } 

     public Builder name(String name) { 
      this.name = name; 
      return this; 
     } 

     public Builder icon(String icon) { 
      this.icon = icon; 
      return this; 
     } 

     public Builder phoneNumber(String phoneNumber) { 
      this.phoneNumber = phoneNumber; 
      return this; 
     } 

     public Builder websiteUrl(String websiteUrl) { 
      this.websiteUrl = websiteUrl; 
      return this; 
     } 

     public Builder builder(int rating) { 
      this.rating = rating; 
      return this; 
     } 

     public Place build() { 
      return new Place(this); 
     } 
    } 

    public Place(Builder builder) { 
     // required parameters 
     longitude = builder.longitude; 
     latitude = builder.latitude; 
     id = builder.id; 

     // optional parameters 
     address = builder.address; 
     types = builder.types; 
     name = builder.name; 
     icon = builder.icon; 
     phoneNumber = builder.phoneNumber; 
     websiteUrl = builder.websiteUrl; 
     rating = builder.rating; 
     challenges = builder.challenges; 
    } 

    public double getLongitude() { 
     return longitude; 
    } 

    public double getLatitude() { 
     return latitude; 
    } 

    public String getId() { 
     return id; 
    } 

    public void setAddress(String address) { 
     this.address = address; 
    } 

    public String getAddress() { 
     return address; 
    } 

    public String getTypes() { 
     return types; 
    } 

    public void setTypes(String types) { 
     this.types = types; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setIconUrl(String icon) { 
     this.icon = icon; 
    } 

    public String getIcon() { 
     return icon; 
    } 

    public void setPhoneNumber(String phoneNumber) { 
     this.phoneNumber = phoneNumber; 
    } 

    public String getPhoneNumber() { 
     return phoneNumber; 
    } 


    public void setWebsiteUrl(String websiteUrl) { 
     this.websiteUrl = websiteUrl; 
    } 

    public String getWebsiteUrl() { 
     return websiteUrl; 
    } 

    public void setRating(int rating) { 
     this.rating = rating; 
    } 

    public int getRating() { 
     return rating; 
    } 

    @Override 
    public String toString() { 
     return "(" + Double.toString(longitude) + ", " + Double.toString(latitude) + ")"; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + ((id == null) ? 0 : id.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     Place other = (Place) obj; 
     if (id == null) { 
      if (other.id != null) 
       return false; 
     } 
     else if (!id.equals(other.id)) 
      return false; 
     return true; 
    } 

    public Vector<Integer> getChallenges() { 
     return new Vector<Integer>(challenges); 
    } 

    public void addChallenges(Integer i) { 
     this.challenges.add(i); 
    } 

    public void showChallenges() { 
     for (Integer i : challenges) { 
      System.out.print(i + ", "); 
     } 
    } 
} 

如果非要設置之前驗證address的說法,我應該在哪裏把在這種情況下驗證地址的代碼?

+0

你是什麼意思輸入?方法參數?提供更多的上下文,所以人們可以滿足您的需求。 – 2011-12-23 22:59:10

+0

@MichałŠrajer:看我的更新。謝謝。 – Chan 2011-12-23 23:09:57

+0

你可能想用'List '而不是'Vector '。你是C++開發人員不是嗎? – 2011-12-23 23:15:49

回答

2

如果您只是看到輸入的字符串格式是否正確或者長度是否正確,那麼您將使用私有方法。如果你要另一方面檢查地址是否正確(在地圖上查看)或更高級的東西,創建一個AddressValidator接口並從該私有方法調用它是有意義的。

私有方法的原因是您可以從構造函數,setter或可以提供地址的任何其他方法調用此方法。接口的原因可能是你想要的接口在線/離線AddressValidator(MockAddressValidator,或者爲每個國家/地區調用不同類別的地址)。由於AddressValidator可以在其他類中重用,爲了保持代碼清潔,我將它創建爲頂級接口+ OnlineAddressValidator。這使得你的類更好的可讀性。爲了實現完全的可配置性,您可能需要考慮如何提供AddressValidator實例,例如通過構造函數或定義爲靜態最終驗證器。

public interface AddressValidator { 
    static class AddressValidatorResult { 
     // some results, you might want to return some useful feedback (if not valid) 

     boolean isValid() { 
      throw new IllegalStateException("Method not implemented yet"); 
     } 
    } 

    public static class AddressValidationException extends Exception { 
     private AddressValidationException(AddressValidatorResult result) { 
      // add some implementation 
     } 
    } 


    // don't throw ValidateException here, invalid addresses are normal for 
    // validators, even if they aren't for the application that uses them 
    AddressValidatorResult validateAddress(String address); 
     // don't throw ValidateException here, invalid addresses are normal for 
     // validators, even if they aren't for the application that uses them 
} 

public class DefaultAddressValidator implements AddressValidator { 

    public static class Params { 
     // some parameters for this specific validator 
    } 

    private final Params params; 

    public DefaultAddressValidator(Params params) { 
     // creates this validator 
     this.params = params; 
    } 

    @Override 
    public AddressValidatorResult validateAddress(String address) { 
     // perform your code here 

     // I don't like "return null" as it may lead to bugs 
     throw new IllegalStateException("Method not implemented yet"); 
    } 
} 


// and use it like this 
private void validateAddress(String address) throws AddressValidationException { 
    // e.g. field AddressValidator set in constructor 
    AddressValidatorResult result = addressValidator.validateAddress(address); 
    if (!result.isValid()) { 
     throw new AddressValidationException(result); 
    } 
} 
+0

我理解你的想法,但將'AddressValidator'作爲接口是我從未想過的事情。我想知道你是否能提供這個想法的最小例子?謝謝。 – Chan 2011-12-23 23:30:07

+0

已添加。現在回答有點大了。 – 2011-12-24 00:01:15

+0

非常感謝;)。 – Chan 2011-12-24 00:16:35

1

我應該將驗證代碼作爲專用幫助器方法還是創建單獨的靜態幫助器類?

這完全取決於你的上下文。不知道你想要實現什麼,不可能說什麼應該是最好的設計。

編輯完成後:海事組織,它仍然不容易告訴你。如果你只需要在應用程序的一個單一點(ID:setter方法)中驗證地址,我會在setter方法中驗證它。如果輸入無效,我應該輸入IllegalArgumentException


是否驗證碼增加對象的大小?

但是,您的第二個問題的答案是。要理解爲什麼,你必須知道面向對象編程是什麼。

一些參考:

1

我應該做的驗證碼爲私有的輔助方法,或創建一個單獨的 靜態輔助類?

這取決於,如果你認爲你還需要重複使用相同的方法在另一大類爲同樣的目的(輸入驗證)最好是在一個單獨的靜態輔助類寫的方法,這樣你就可以重複使用方法並輕鬆維護。 如果您每次需要進行更改時都要在幾個類中編寫相同的專用幫助程序方法,則必須編輯每個類中的每個方法,帶有靜態幫助程序類,您只能在一處更改代碼...

+0

不錯的想法!我想測試我的方法也會容易得多,因爲我不需要公開所有東西。 – Chan 2011-12-23 23:19:05

0

我傾向於隨得到驗證()和set()方法儘可能 - 呼籲共同任務外部靜態方法,如檢查日期或清潔輸入(即避免SQL注入)

如果你只使用(並且只會使用)在一個類中的驗證,保持它作爲一個私人幫手方法。如果有疑問,我傾向於將功能拉到靜態幫助類中。它對代碼量沒有太大的影響,沒有更多的努力來實現,並且更加靈活。

0

簡短的回答是:你應該按照你的框架告訴你的方式來實現你的驗證代碼。通常,這是一種公共方法或註釋。接口也可以工作。如果您添加代碼,您的班級規模將會增加。

數據驗證應該由您的軟件的基礎結構自動調用。這有助於防止程序員忘記調用適當的代碼。所以,這些方法應該是公開的(一個接口也可以)。

框架像Struts,Spring,Hibernate和有他們自己的驗證系統。 Java EE利用bean驗證。

我推薦bean驗證,因爲它執行驗證,不管輸入源是什麼。當大多數人想到輸入驗證時,他們會想到來自用戶的數據,例如HTTP請求,命令控制檯,Swing文本字段。 Spring和Struts驗證通常適用於這些情況。但是在爲企業開發的長期計劃中,其他數據源常常被引入,例如SQL數據庫從另一個程序更新,崩潰後數據庫恢復,企業服務總線,JMS。

這就是爲什麼我更喜歡bean驗證。缺點是「安全來源」(您知道的數據未經處理)會被不必要地驗證。但憑藉今天的處理能力,這應該很少成爲一個重要的關注點。 Java EE Tutorial