我有一个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
}
}
答案 0 :(得分:2)
你错过了enum
的惊人灵活性,它们本身就是完全成熟的对象,因此可以实现接口。如果你使enum本身能够作为工厂运行,那么一切都变得简单。
这里大大简化了使用enum
作为工厂的演示。
interface Loader {
public Plugin load();
}
enum PluginType implements Loader {
Service {
@Override
public Plugin load() {
return new ServiceClassLoader();
}
},
Channel {
@Override
public Plugin load() {
return new ChannelClassLoader();
}
};
}
public void loadPlugin(PluginType type) {
Plugin plugin = type.load();
}
public void test() {
loadPlugin(PluginType.Channel);
}
答案 1 :(得分:2)
三个选项:
newClassLoader()
中声明一个抽象的PluginManager
方法,该方法在ServiceManager
中被覆盖以返回新的ServiceClassLoader
等PluginType
更改为Class<? extends ClassLoader>
,将其存储在字段中(例如classLoaderClass
),然后在需要时调用classLoader.newInstance()
PluginType
成为枚举(如果它还没有),它有自己的方法来创建新的ClassLoader
。(由于其他原因,您是否需要PluginType
并不清楚 - 如果您不这样做,那么就没有。)
答案 2 :(得分:1)
向PluginManager
添加一个抽象方法以创建一个类加载器,并根据需要调用它。子类应该重写该方法,返回适当的子类:
public abstract class PluginManager {
public PluginManager() {
pluginLoader = MakeClassLoader();
}
...
protected abstract PluginClassLoader MakeClassLoader();
}
public class ServiceManager extends PluginManager {
...
protected abstract PluginClassLoader MakeClassLoader() {
return new ServiceClassLoader();
}
}
public class ChannelManager extends PluginManager {
...
protected abstract PluginClassLoader MakeClassLoader() {
return new ChannelClassLoader();
}
}
这实现了Factory Method设计模式。