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: