我有一个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
}
}
您错过了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);
}
三个选项:
- 在
PluginManager
中声明一个抽象的newClassLoader()
方法,在ServiceManager
中被覆盖以返回新的ServiceClassLoader
等 - 将参数类型从
PluginType
更改为Class<? extends ClassLoader>
,将其存储在字段中(例如classLoaderClass
(,然后在需要时致电classLoader.newInstance()
PluginType
创建一个枚举(如果还没有(,它有自己的方法来创建新ClassLoader
。
(目前尚不清楚您是否出于其他原因需要PluginType
- 如果您不需要,那就不要使用它。
添加一个抽象方法,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();
}
}
这将实现工厂方法设计模式。