A SIMPLE SOLUTION
You can save your Class<T> -> Handler<T> mappings Class<T> -> Handler<T> to Map . Sort of:
Map<Class<T>, Handler<T>> registry = new HashMap<>(); public void registerHandler(Class<T> dataType, Class<? extends Handler> handlerType) { registry.put(dataType, handlerType); } public <T> Handler<T> getHandler(Class<T> clazz) { return registry.get(clazz).newInstance(); }
Initialize the handlers in some place (maybe in the factory itself):
factory.registerHandler(String.class, StringHandler.class); factory.registerHandler(Date.class, DateHandler.class);
And in another place you create and use them:
Handler<String> stringhandler = factory.getHandler(String.class); Handler<Date> dateHandler = factory.getHandler(Date.class);
MORE INTEGRATED SOLUTION
You can βscanβ classes using reflection and instead of manually registering the mappings Class<T> -> Handler<T> , do this using reflection.
for (Class<? extends Handler> handlerType : getHandlerClasses()) { Type[] implementedInterfaces = handlerType.getGenericInterfaces(); ParameterizedType eventHandlerInterface = (ParameterizedType) implementedInterfaces[0]; Type[] types = eventHandlerInterface.getActualTypeArguments(); Class dataType = (Class) types[0]; // <--String or Date, in your case factory.registerHandler(dataType, handlerType); }
Then you create and use them as described above:
Handler<String> stringhandler = factory.getHandler(String.class); Handler<Date> dateHandler = factory.getHandler(Date.class);
To implement getHandlerClasses() , view this one to scan all classes in jar . For each class, you should check if it is a Handler :
if (Handler.class.isAssignableFrom(scanningClazz) //implements Handler && scanningClazz.getName() != Handler.class.getName()) //it is not Handler.class itself { //is a handler! }
Hope this helps!