用Java创建输入验证方法的良好实践是什么?

Cha*_*han 1 java coding-style

如果我想验证输入内容,是否应该将验证代码作为私有帮助器方法或创建单独的静态帮助器类?验证代码是否会增加对象的大小?

更多信息

假设我有一堂课

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 + ", ");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果address在设置参数之前必须先验证参数,在这种情况下应将用于验证地址的代码放在哪里?

Maa*_*wes 5

如果您只是在看输入的String的格式正确或长度正确,那么您将使用私有方法。另一方面,如果您要检查地址是否正确(在地图上查找地址)或更高级的内容,则可以创建一个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);
    }
}
Run Code Online (Sandbox Code Playgroud)