Tag Archives: magic

Java Tips: Process Object Based On Its Type Without if-then-else Solution

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:

  1. You don’t want if-then-else solution which is obviously not great for long-term
  2. 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?