Reputation: 179
I am writing a code in Java to enable different components. Every component needs to satisfy a certain set of conditions to get enabled. Every condition is basically a method which performs some logic & returns boolean. Currently, I have written a code in which there is a different method to perform enable logic for each component & that corresponding method performs the conditional operations to return boolean. My current implementation of enabling different components looks something like this :
private boolean shouldEnableComponent1() {
String param1 = getParam1();
String param2 = getParam2();
String param3 = getParam3();
if(checkCondition1(param1) && checkCondition2(param2) && checkCondition3(param3) {
return true;
} else {
return false;
}
}
private boolean shouldEnableComponent2() {
String param1 = getParam1();
String param2 = getParam2();
String param4 = getParam4();
if(checkCondition1(param1) && checkCondition2(param2) && checkCondition4(param4) {
return true;
} else {
return false;
}
}
Note that different shouldEnableComponentN() methods may have to call same conditional methods like in above case both shouldEnableComponent1() & shouldEnableComponent2() are calling checkCondition1() & checkCondition2() methods. The difference between their enabling condition is the 3rd conditional check i.e. checkCondition3() in case of component1 & checkCondition4() in case of component2.
This is the most obvious implementation which I could come up with but it has few problems -
Duplicity - Since there is an overlap between conditional checks of different components, that part of the code is duplicated.
Scalability - Today there are 3 components, tomorrow there will be 10 components. So, I will need to implement 10 different methods for each components. That's definitely bad.
I am thinking of Strategy pattern for this use case but I am not sure how to implement it here. Is strategy pattern the correct choice? If yes, please give high level idea of how it will be implemented i.e. where will I put the common variables which need to be used across classes, where will the common logic part of all concrete classes be placed etc. Or is there any other design pattern which will be better than strategy pattern for this use case? Thanks in advance
Upvotes: 3
Views: 1006
Reputation: 42541
One idea that comes to my mind is to provide some logical name to parameters (assuming they're all strings as you've stated in the question):
Given the set of parameters is known in compile time you could create a "registry" of parameters:
enum ParamName {
PARAM1, PARAM2, PARAM3... PARAM_N;
}
class ConditionChecker {
private Map<ParamName, Predicate<String>> registry;
public ConditionChecker() {
map.put(ParamName.PARAM1, this::conditionCheck1);
map.put(ParamName.PARAM2, this::conditionCheck2);
// populate the map with all conditions for all possible parameters
}
// knows how to check param1
private Boolean conditionCheck1(String param1) {
...
}
// knows how to check param2
private Boolean conditionCheck2(String param2) {
...
}
...
}
Now Provide a "generic" condition checking method:
class ConditionChecker { // the same class as above, continuing...
public boolean checkAll(Map<ParamName, String value> allParams) {
// for each element in the map call
for(Entry<ParamName, String> entry : allParams.entrySet()) {
if(! registry.get(entry.getKey()).accept(entry.getValue())) {
return false; // at least one check failed
}
}
// all validations passed
return true;
}
}
Now in shouldEnableComponent1
which possesses the information "which params exactly should be validated" you can do something like this:
boolean shouldEnableComponent1() {
Map<ParamName, String> paramMap = extractMapForParams(PARAM1, PARAM2, PARAM3);
return conditionChecker.checkAll(paramMap);
}
Upvotes: 1