Я пытаюсь определить лучший способ создать новый экземпляр класса, основанный на том, какие классы доступны в пути к классам во время выполнения.
Например, у меня есть библиотека, которая требует, чтобы ответ JSON обрабатывался несколькими классами. Библиотека имеет следующий интерфейс:
JsonParser.java
:
public interface JsonParser {
<T> T fromJson(String json, Class<T> type);
<T> String toJson(T object);
}
Этот класс имеет несколько реализаций, то есть GsonJsonParser
, JacksonJsonParser
, Jackson2JsonParser
, и в настоящее время пользователь библиотеки должен "выбрать" свою реализацию, которая будет использоваться на основе той библиотеки, в которую они были включены их проект. Например:
JsonParser parser = new GsonJsonParser();
SomeService service = new SomeService(parser);
То, что я хотел бы сделать, - это динамически выбрать, какая библиотека находится в пути к классам, и создать соответствующий экземпляр, чтобы пользователь библиотеки не мог об этом думать (или даже должен знать внутренняя реализация другого класса анализирует JSON).
Я рассматриваю нечто похожее на следующее:
try {
Class.forName("com.google.gson.Gson");
return new GsonJsonParser();
} catch (ClassNotFoundException e) {
// Gson isn't on classpath, try next implementation
}
try {
Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
return new Jackson2JsonParser();
} catch (ClassNotFoundException e) {
// Jackson 2 was not found, try next implementation
}
// repeated for all implementations
throw new IllegalStateException("You must include either Gson or Jackson on your classpath to utilize this library");
Будет ли это подходящим решением? Это похоже на хак, а также использует исключения для управления потоком.
Есть ли лучший способ сделать это?