I want to share my answer for this question on StackOverflow.
Say you want to process several objects with different types. Each type must be processed differently but some concerns are:
- You don’t want if-then-else solution which is obviously not great for long-term
- Configuration is also bad for the same reason
So how is the solution? This is the solution that is using library from Reflections.
public class A { }
public class B { }
import java.lang.reflect.ParameterizedType; public abstract class Processor<T> { private final Class<T> processedClass; public Processor() { ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass(); processedClass = (Class<T>) parameterizedType.getActualTypeArguments()[0]; } public Class<T> getProcessedClass() { return processedClass; } protected abstract void process(T message); }
public class ProcessorA extends Processor<A> { @Override protected void process(A message) { System.out.println("Processing object A"); } }
public class ProcessorB extends Processor<B> { @Override protected void process(B message) { System.out.println("Processing object B"); } }
import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.reflections.Reflections; public class Adapter { private Map<Class<?>, Processor<Class<?>>> mapping = new HashMap<Class<?>, Processor<Class<?>>>(); public Adapter() throws Exception { Reflections r = new Reflections(""); Set<Class<? extends Processor>> subTypesOf = r.getSubTypesOf(Processor.class); for (Iterator iterator = subTypesOf.iterator(); iterator.hasNext();) { Class<? extends Processor> c = (Class<? extends Processor>) iterator.next(); Constructor<? extends Processor> constructor = c.getConstructor(); Processor p = constructor.newInstance(); mapping.put(p.getProcessedClass(), p); } } public <T> Processor<T> getProcessor( Class<? extends T> c) { return (Processor<T>) mapping.get(c); } }
public class Main { public static void main(String[] args) throws Exception { Adapter adapter = new Adapter(); A a = new A(); adapter.getProcessor(a.getClass()).process(a); B b = new B(); adapter.getProcessor(b.getClass()).process(b); } }
The console after running main method:
14:01:37.640 [main] INFO org.reflections.Reflections - Reflections took 375 ms to scan 4 urls, producing 222 keys and 919 values Processing object A Processing object B
It’s kind of magic, isn’t it?