У меня есть PluginClassLoader
, который является абстрактным классом, который обеспечивает 99% функциональности для загрузчиков классов моего проекта. У меня есть 2 подкласса (ServiceClassLoader
и ChannelClassLoader
), которые простираются на PluginClassLoader
и представляют собой немного больше, чем обертки и некоторые настраиваемые протоколирования. 99% логики одинаковы между двумя реализациями.Отделить абстрактные данные класса от расширенных реализаций
Я тогда PluginManager
, который также является абстрактным классом, который имеет 2 реализаций, которые расширяют его (ServiceManager
и ChannelManager
), которые являются оболочками плюс индивидуальные каротаж и более удобный конструктор.
Проблема, с которой я столкнулся, в моем PluginManager
должна быть способна создать экземпляр нового типа загрузчика класса либо ServiceClassLoader
, либо ChannelClassLoader
. Я пытаюсь избежать привязки своего PluginManager
к его текущим реализациям (т. Е. Я хочу, чтобы гибкость в возможности добавлять будущие реализации, но не изменяла логику PluginManager
), поэтому старайтесь избегать прохождения в каком-то Enum
и используя некоторые из них:
if (classLoaderType instanceof ClassLoaderType.SERVICE) {
// do logic for instantiating ServiceClassLoader
}
Пример иерархии классов:
public abstract class PluginManager {
// logic for managing plugins and when to load them
// ...
// somewhere deep in a loadPlugin(final File directory) method
pluginLoader = new PluginClassLoader(); // <-- not valid, can't instantiate
// an abstract class,
// and it's of the wrong type!
}
public abstract class PluginClassLoader extends URLClassLoader {
// class loader logic
}
public class ServiceManager extends PluginManager {
// wrapper for PluginManager with some customized logging
}
public class ServiceClassLoader extends PluginClassLoader {
// wrapper for PluginClassLoader with some customized logging
}
Попытка избежать делать что-то вроде:
public abstract class PluginManager {
private final PluginType pluginType;
public PluginManager(final PluginType pluginType) {
this.pluginType = pluginType;
}
// logic ...
// somewhere deep in the loadPlugin(final File directory) method
if (pluginType instanceof PluginType.SERVICE) {
pluginLoader = new ServiceClassLoader();
// more logic
} else if (plugintype instanceof PluginType.CHANNEL) {
pluginLoader = new ChannelClassLoader();
// more logic
}
}
Мне непонятно, что нужно для определения загрузчика классов.Если ServiceManager всегда создает ServiceClassLoader, а в каком-то другом подклассе PluginManager всегда используется PluginClassLoader? –
@JonSkeet да именно это. Я пытаюсь избежать переопределения метода loadPlugin() для каждого менеджера, поскольку 99% деталей идентичны, это действительно только эта строка, которая будет отличаться. – SnakeDoc