Skip to content
Advertisement

Java – Using Validators to implement variable numbers of “if” statements

According to the solution presented here by daniu, the Composite pattern can be used to maintain a list of Validators to test all the needed conditional tests. But I didn’t understand how to use it. Below are my conditional tests and the provided code that he made available.

My conditional tests:

boolean namesPatientEqualAndMotherSimilar = (lvNamePatient == 0 && lvNameMother <= 10);
boolean namesPatientAndMotherSimilar = (lvNamePatient <= 10 && lvNameMother <= 10);
boolean equalOrSimilarBirthDate = (lvPatientBirth < 2);
boolean twin = patientTwin.equals("yes") && patient.getTwin().equals("yes");

if (namesPatientEqualAndMotherSimilar && equalOrSimilarBirthDate && twin) {
    return true;
} else if (namesPatientAndMotherSimilar && equalOrSimilarBirthDate && twin) {
    return false;
} else if (namesPatientAndMotherSimilar && equalOrSimilarBirthDate && !twin) {
    return true;
} else if (namesPatientAndMotherSimilar && !equalOrSimilarBirthDate) {
    return false;
}

Validator interface:

public interface Validator<SomeObejct>{
    public Result validate(SomeObject o);
} 

Interface implementation:

class ValidatorComposite<T> implements Validator<T> {
    
    List<Validator<T>> validators = new ArrayList<>();

    public void addValidator(Validator<T> add) {
        validators.add(add)); }

    public Result validate(T toValidate) {
        Result result = Result.OK;
        for (Validator<T> v : validators) {
            result = v.validate(toValidate);
            if (result != Result.OK) break;
        }
        return result;
    }
}

Use of implementation:

ValidatorComposite<SomeObject> val = new ValidatorComposite<>();
val.addValidator(so -> condition1 ? block1(so) : Result.OK);
val.addValidator(so -> condition2 ? block2(so) : Result.OK);

Thank you in advance.

Advertisement

Answer

For simplicity, lets assume that we have an InfoObject object with the fields.

public class InfoObject{
   boolean namesPatientEqualAndMotherSimilar;
   boolean namesPatientAndMotherSimilar;
   boolean equalOrSimilarBirthDate;
   boolean twin;
}

And our task is to validate that this InfoObject input is correct. One approach was to use the if-else condition, but if the number of validations required increases then the if-else code might become messy.

Next, we can directly use the ValidatorComposite class and define our custom validators.

ValidatorComposite<InfoObject> completeValidator = new ValidatorComposite<>();
val.addValidator(infoObject -> firstCheck(infoObject) ? Result.OK : Result.NOT_OK);
val.addValidator(infoObject -> secondCheck(infoObject) ? Result.NOT_OK : Result.OK);
val.addValidator(infoObject -> thirdCheck(infoObject) ? Result.OK : Result.NOT_OK);
val.addValidator(infoObject -> fourthCheck(infoObject) ? Result.NOT_OK : Result.OK);

Result result = completeValidator.validate(infoObject);
if(result == Result.OK){
  return true;
}
return false;

And we can define the following functions. Sorry for the functions name, I didn’t know the actual use case, so used some dummy names:

public boolean firstCheck(InfoObject infoObject){
  return infoObject.getNamesPatientEqualAndMotherSimilar() && infoObject.getEqualOrSimilarBirthDate() && infoObject.getTwin();
}

public boolean secondCheck(InfoObject infoObject){
  return infoObject.getNamesPatientAndMotherSimilar() && infoObject.getEqualOrSimilarBirthDate() && infoObject.getTwin();
}

public boolean thirdCheck(InfoObject infoObject){
  return infoObject.getNamesPatientAndMotherSimilar() && infoObject.getEqualOrSimilarBirthDate() && !infoObject.getTwin();
}

public boolean fourthCheck(InfoObject infoObject){
  return infoObject.getNamesPatientAndMotherSimilar() && !infoObject.getEqualOrSimilarBirthDate();
}

How does this code work?

We defined a list of validators. The validate() function will call all the validators one by one, and it will stop when one of the validators returns the NOT_OK result.

In addValidator function, we have a lambda function infoObject -> fourthCheck(infoObject) ? Result.NOT_OK : Result.OK, which returns a functional interface.

There are a lot of concepts involved in this example, to learn about more concepts please refer to:

  1. Composite pattern
  2. Lambda Expressions
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement