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: