简体   繁体   English

为 java bean 设置字段的更好方法

[英]better approach to set fields for java bean

I want to set different field value everytime when I create a bean.我想每次创建 bean 时都设置不同的字段值。 But there are a lot of field to set.但是有很多字段要设置。 I can set those by using constructor.我可以使用构造函数来设置它们。 But if there is a better approach to do this?但是如果有更好的方法来做到这一点呢?

The code just like below, there are five errors, and every time using the bean need to specify different five errors.代码如下,有五个错误,每次使用bean需要指定不同的五个错误。 I am specifing those errors by constructor, this can work.我正在通过构造函数指定这些错误,这可以工作。 But I know this is not an elegant way.但我知道这不是一种优雅的方式。

Can I do this in better way ?我能以更好的方式做到这一点吗?

public class WildcardNumberValidator extends BaseValidator<String> {

    private ErrorInfo wildcardCountError;
    private ErrorInfo regionWildcardError;
    private ErrorInfo festivalWildcardError;
    private ErrorInfo backwardWildcardError;
    private ErrorInfo keyWildcardError;
    private ErrorInfo totalWildcardError;

    public WildcardNumberValidator(ErrorInfo wildcardCountError,
                                   ErrorInfo regionWildcardError,
                                   ErrorInfo festivalWildcardError,
                                   ErrorInfo backwardWildcardError,
                                   ErrorInfo keyWildcardError,
                                   ErrorInfo totalWildcardError) {
        this.wildcardCountError = wildcardCountError;
        this.regionWildcardError = regionWildcardError;
        this.festivalWildcardError = festivalWildcardError;
        this.backwardWildcardError = backwardWildcardError;
        this.keyWildcardError = keyWildcardError;
        this.totalWildcardError = totalWildcardError;
    }


    @Override
    public boolean validate(ValidatorContext context, String str) {

        int totalNum = regionNum + festivalNum + keyNum + regionNum;
        if (maxRegionNum != null && regionNum > maxRegionNum) {
            context.addError(regionWildcardError);
            return false;
        }
        if (maxFestivalNum != null && festivalNum > maxFestivalNum) {
            context.addError(festivalWildcardError);
            return false;
        }
        if (maxBackwardNum != null && backwardNum > maxBackwardNum) {
            context.addError(backwardWildcardError);
            return false;
        }
        if (maxKeyNum != null && keyNum > maxKeyNum) {
            context.addError(keyWildcardError);
            return false;
        }
        if (maxTotalNum != null && totalNum > maxTotalNum) {
            context.addError(totalWildcardError);
            return false;
        }
        return true;
    }
}

You can try accepting various ErrorInfo as collection.您可以尝试接受各种ErrorInfo作为集合。 Let's say Map of errorInfoType and actual ErrorInfo object.假设errorInfoType和实际ErrorInfo对象的Map errorInfoType can be of Enum type ie Map<ErrorInfoEnum, ErrorInfo> errorInfoMap . errorInfoType可以是Enum类型,即Map<ErrorInfoEnum, ErrorInfo> errorInfoMap

You can modify your code something like below and try:您可以像下面那样修改您的代码并尝试:

public class WildcardNumberValidator extends BaseValidator<String> {

    private Map<ErrorInfoEnum, ErrorInfo> errorInfoMap = new HashMap<>();

    public WildcardNumberValidator(Map<ErrorInfoEnum, ErrorInfo> errorInfoMap) {
        this.errorInfoMap = errorInfoMap;
    }


    @Override
    public boolean validate(ValidatorContext context, String str) {

        int totalNum = regionNum + festivalNum + keyNum + regionNum;
        if (maxRegionNum != null && regionNum > maxRegionNum) {
            context.addError(errorInfoMap.get(ErrorInfoEnum.REGION_WILD_CARD_ERROR));
            return false;
        }
        if (maxFestivalNum != null && festivalNum > maxFestivalNum) {
            context.addError(errorInfoMap.get(ErrorInfoEnum.FESTIVAL_WILD_CARD_ERROR));
            return false;
        }
        if (maxBackwardNum != null && backwardNum > maxBackwardNum) {
            context.addError(errorInfoMap.get(ErrorInfoEnum.BACKWARD_WILD_CARD_ERROR));
            return false;
        }
        if (maxKeyNum != null && keyNum > maxKeyNum) {
            context.addError(errorInfoMap.get(ErrorInfoEnum.KEY_WILD_CARD_ERROR));
            return false;
        }
        if (maxTotalNum != null && totalNum > maxTotalNum) {
            context.addError(errorInfoMap.get(ErrorInfoEnum.TOTAL_WILD_CARD_ERROR));
            return false;
        }
        return true;
    }
}

ErrorInfoEnum : ErrorInfoEnum

enum ErrorInfoEnum {
    WILD_CARD_COUNT_ERROR,
    REGION_WILD_CARD_ERROR,
    FESTIVAL_WILD_CARD_ERROR,
    BACKWARD_WILD_CARD_ERROR,
    KEY_WILD_CARD_ERROR,
    TOTAL_WILD_CARD_ERROR
}

Better yet, if ErrorInfo instances are immutable, you can make ErrorInfo itself an enum :更好的是,如果ErrorInfo实例是不可变的,您可以将ErrorInfo本身设置为enum

public class WildcardNumberValidator extends BaseValidator<String> {
    enum ErrorInfo {
        COUNT_ERROR(1, "count ..."),
        REGION_ERROR(2, "foo"),
        FESTIVAL_ERROR(129, "bar"),
        BACKWARD_ERROR(76, "fred"),
        KEY_ERROR(99, "baz"),
        TOTAL_ERROR(101, "xyzzy");
        
        // whatever your ErrorInfo does
        private int code;
        private String message;

        WildcardErrorInfo(int code, String message) {
            this.code = code;
            this.message = message;
        }
    }


    // default constructor
    public WildcardNumberValidator() {

    }


    @Override
    public boolean validate(ValidatorContext context, String str) {

        int totalNum = regionNum + festivalNum + keyNum + regionNum;
        if (maxRegionNum != null && regionNum > maxRegionNum) {
            context.addError(ErrorInfo.REGION_ERROR);
            return false;
        }
        ...
        return true;
    }
}

You can try to inverse the responsibility, instead of WildcardNumberValidator trying to validate your input, you can make ErrorInfo do that.您可以尝试反转责任,而不是 WildcardNumberValidator 尝试验证您的输入,您可以让 ErrorInfo 这样做。

public class WildcardNumberValidator extends BaseValidator<String> {

    private List<ErrorInfo> errors;

    public WildcardNumberValidator(List<ErrorInfo> errors) {
        this.errors=errors;
    }


    @Override
    public boolean validate(ValidatorContext context, String str) {

    List<ErrorInfo> faildChecks= errors.stream()
        .filter(error->error.check(str))
        .collect(Collectors.toList());

    if(faildChecks.empty()){
        return true;
    }

    faildChecks.forEach(error->context.addError(error));
    return false;
    }
}

where ErrorInfo will like this:其中 ErrorInfo 会喜欢这个:


class ErrorInfo {
    private Predicate<String> predicate; 
    void setPredicate(Predicate<String> predicate){
        this.predicate=predicate;
    }
    boolean check(String input){
        return predicate.test(input);
    }   
}

How to use:如何使用:

void test(){
    //... do other stuff
    int totalNum = regionNum + festivalNum + keyNum + regionNum;
    ErrorInfo wildcardCountError= // init your ErrorInfo;
    wildcardCountError.setPredicate(input-> maxRegionNum != null && regionNum > maxRegionNum)
    // the same for other ErrorInfo,
    WildcardNumberValidator validator = new WildcardNumberValidator(List.of(wildcardCountError,...other errors);

}

A couple of suggested ways to do this are to use static factory methods or builder pattern.一些建议的方法是使用静态工厂方法或构建器模式。

Factory method can give you freedom to name your methods.工厂方法可以让你自由地命名你的方法。 Builder can help you build objects in steps. Builder 可以帮助您逐步构建对象。 There are other advantages as well.还有其他优点。 This is one of the first guidelines suggested in the Effective Java book.这是 Effective Java 一书中建议的第一个准则之一。 I will recommended the book highly.我会高度推荐这本书。 Table of Contents目录

A library you can take a look at is lombok .您可以查看的一个库是lombok You can declare a class as data class/ builder , etc and it will save of even writing those boilerplate lines of code.您可以将一个类声明为data类/ builder等,它甚至可以节省编写那些样板代码行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM