Skip to content
Advertisement

What is the name of the design pattern where I dynamically pick the correct implementation based on data?

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);
    }

}

Answer

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());
Advertisement