javadesign-patternsstatic-factory

static factory builder trouble


Needing to create an unspecified number of objects, I tried to create a builder that do that. All was well until I realized that my builder creates all objects with their properties having the same values.

So when I call the builder:

ValidationHelper v = new ValidationHelper.HelperBuilder()
        .addHelper("ICAO Identifier", icaoIdentifier, rulesICAO)
        .addHelper("Long Name", longName, rulesLongName)
        .build();

... I'll have 2 objects and their properties will have values of the last object the builder was asked to create.

To start with, is factory builder the prudent approach to this? Secondly, is my builder salvageable?

Builder:

public class ValidationHelper {

    private static ArrayList<HelperBuilder> validatorHelpers = new ArrayList();


    public static class HelperBuilder {

        private String txtFieldName;
        private String txtFieldValue;

        private List<Integer> valCodes = new ArrayList<Integer>();

        private ArrayList<HelperBuilder> innerValidatorHelpers = new ArrayList<HelperBuilder>();

        public HelperBuilder() {}

        public final HelperBuilder addHelper(String txtFieldName, String txtFieldValue, int[] validationCodes) {

            this.txtFieldName = txtFieldName;
            this.txtFieldValue = txtFieldValue;
            for( int i = 0; i < validationCodes.length; i++ ){
                getValCodes().add((Integer) validationCodes[i]);
            }

            innerValidatorHelpers.add(this);
            return this;
        }

        public final ValidationHelper build() {
            return new ValidationHelper(this);
        }

        public String getTxtFieldName() {
            return txtFieldName;
        }

        public String getTxtFieldValue() {
            return txtFieldValue;
        }

        public List<Integer> getValCodes() {
            return valCodes;
        }
    }//end HelperBuilder

    private ValidationHelper(HelperBuilder helperBuilder) {
        validatorHelpers = helperBuilder.innerValidatorHelpers;
    }

    public void setHelpers(ArrayList validatorHelpers) {
        validatorHelpers = validatorHelpers;
    }

    public ArrayList getHelpers() {
        return validatorHelpers;
    }
}

EDIT/FIXED:

So for what it's worth, here's the revised builder. It needed another constructor that could properly initialize an instance of what it's supposed to build.

public class ValidationHelper {

    private static ArrayList<HelperBuilder> validatorHelpers = new ArrayList();

    public static class HelperBuilder {

        private String txtFieldName;
        private String txtFieldValue;

        private List<Integer> valCodes = new ArrayList<Integer>();

        private ArrayList<HelperBuilder> innerValidatorHelpers = new ArrayList<HelperBuilder>();

        public HelperBuilder() {}
        public HelperBuilder(String txtFieldName, String txtFieldValue, int[] validationCodes) {

            this.txtFieldName = txtFieldName;
            this.txtFieldValue = txtFieldValue;

            for (int i = 0; i < validationCodes.length; i++) {
                valCodes.add((Integer) validationCodes[i]);
            }

        }

        public final HelperBuilder addHelper(String txtFieldName, String txtFieldValue, int[] validationCodes) {
            innerValidatorHelpers.add( new HelperBuilder(txtFieldName, txtFieldValue, validationCodes) );
            return this;
        }

        public final ValidationHelper build() {
            return new ValidationHelper(this);
        }

        public String getTxtFieldName() {
            return txtFieldName;
        }

        public String getTxtFieldValue() {
            return txtFieldValue;
        }

        public List getValCodes() {
            return valCodes;
        }
    }//end HelperBuilder

    private ValidationHelper(HelperBuilder helperBuilder) {
        validatorHelpers = helperBuilder.innerValidatorHelpers;
    }

    public ArrayList getHelpers() {
        return validatorHelpers;
    }
}

Solution

  • Each time you just overwrite the values in

    private String txtFieldName;
    private String txtFieldValue;
    

    and the last one winns. So you create only 1 HelperInstance here

    ValidationHelper v = new ValidationHelper.HelperBuilder()
    

    and the fields name and value are overwritten each time you call addHelper(). But you need to create an instance for each "configuration". So addHelper should create a new Instance and add it into

    private ArrayList<HelperBuilder> innerValidatorHelpers = ...;