Originally I picked the correct User implementation, based on domain and realm data from the Java EE server. However that was company code, so I had to rewrite the example with numbers. I hope the underlying pattern is still understandable though. For those unfamiliar with CDI, @Inject Instance allows you to iterate through all implementations of an interface.
public class NumberPicker {
@Inject
private Instance<NumberMapper> mappers;
public Number parse (String string) {
for( NumberMapper mapper : mappers ){
if( mapper.isApplicable(string) ){
return mapper.apply(string);
}
}
throw new InvalidArgumentException("Can not parse " + string);
}
}
public interface NumberMapper {
boolean isApplicable (String string);
Number apply (String string);
}
public class ByteMapper implements NumberMapper {
@Override
public boolean isApplicable (String string) {
return string.length() == 1;
}
@Override
public Number apply (String string) {
return (byte) string.charAt(0);
}
}
public class IntegerMapper implements NumberMapper {
@Override
public boolean isApplicable (String string) {
if( string.length() == 1 ){
return false;
}
try {
Integer.parseInt(string);
return true;
}catch( NumberFormatException e ){
return false;
}
}
@Override
public Number apply (String string) {
return Integer.parseInt(string);
}
}
public class FloatMapper implements NumberMapper
@Override
public boolean isApplicable (String string) {
if( string.length() == 1 ) {
return false;
}
try {
Integer.parseInt(string);
return false;
}catch( NumberFormatException e){
}
try {
Float.parseFloat(string);
return true;
}catch( NumberFormatException e){
return false;
}
}
@Override
public Number apply (String string) {
return Float.parseFloat(string);
}
}
I think you are talking about the Strategy Pattern:
public interface Strategy {
boolean test();
void execute();
}
public class FirstStrategy implements Strategy{
@Override
public boolean test() {
//returns true or false
}
@Override
public void execute() {
//your custom implementation
}
}
public class SecondStrategy implements Strategy{
@Override
public boolean test() {
//returns true or false
}
@Override
public void execute() {
//your custom implementation
}
}
Then you have your list of strategies:
List<Strategy> strategiesList = List.of(new FirstStrategy(), new SecondStrategy());
Thus:
strategiesList.stream()
.filter(aStrategy -> aStrategy.test())
.findFirst()
.ifPresent(aStrategy -> aStrategy.execute());