I am designing a validation module. It has 100 error codes(i.e. errcd_01, errcd_02,..,errcd_100) to be validated. In input I am getting a specific error code(i.e. errcd_01) out of above 100. Module should perform validation for that specific error code.
I am using factory pattern.
/* Interface */
public interface validateErrCd {
void check_errcd();
}
/* Concrete classes implementing the same interface */
public class validateErrCd_01 implements validateErrCd {
@Override
public void check_errcd() {
//business logic related to errcd_01
}
}
public class validateErrCd_02 implements validateErrCd {
@Override
public void check_errcd() {
//business logic related to errcd_02
}
}
.
.
.
public class validateErrCd_100 implements validateErrCd {
@Override
public void check_errcd() {
//business logic related to errcd_100
}
}
/* Factory */
public class ErrorValidationFactory {
//use check_errcd method to get object of type shape
public validateErrCd getValidation(String errorCode){
if(errorCode == null){
return null;
}
if(errorCode.equalsIgnoreCase("errcd_01")){
return new validateErrCd_01();
} else if(errorCode.equalsIgnoreCase("errcd_02")){
return new validateErrCd_02();
} ..
.......
else if(errorCode.equalsIgnoreCase("errcd_100")){
return new validateErrCd_100();
}
else {
return null;
}
}
}
/* I am using the Factory to get object of concrete class by passing an specific error code to be validated (i.e. "errcd_01"). */
public class FactoryPatternDemo {
public static void main(String[] args) {
ErrorValidationFactory errorFactory = new ErrorValidationFactory();
//get an object of validateErrCd_01 and call its check_errcd method.
validateErrCd errcd01 = errorFactory.getValidation("errcd_01");
//call check_errcd method of validateErrCd_01
errcd01.check_errcd();
}
}
Now due to multiple if/else inside Factory class ErrorValidationFactory, I am getting couple of CI/CD errors while performing mvn clean install. e.g. [MethodLength] - checkstyle, Rule:CyclomaticComplexity - PMD.
So is there a way I can replace if/else, switch case kind of decision making inside factory which does not trigger above CI/CD errors in Java?
Note : If possible I would like to avoid reflection
You could use a Map
:
public class ErrorValidationFactory {
private Map<String,Supplier<validateErrCd>> creators=new HashMap<>();
public ErrorValidationFactory(){
creators.put("errcd_100",validateErrCd_100::new);
//Same for others
}
//use check_errcd method to get object of type shape
public validateErrCd getValidation(String errorCode){
if(errorCode == null){
return null;
}
return creators.getOrDefault(errorCode,()->null);
}
}
Supplier
is a functional interface that contains a method returning an object. SomeClass::new
or ()->new SomeClass()
means that the constructor of the class will be used for that.
This allows to to create the instances later.
If you want to create the Map
only once, you can make it static
and populate it in a static initializer.
However, if you really want to dynamically get the constructors, you would need to use reflection.