2011-12-23 58 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