从扩展实现中分离抽象类详细信息

时间:2014-12-04 17:11:28

标签: java classloader abstract-class extends

我有一个PluginClassLoader,它是一个抽象类,为我的项目的类加载器提供99%的功能。我有2个子类(ServiceClassLoaderChannelClassLoader)扩展PluginClassLoader并且只是包装器和一些自定义日志记录。两种实现之间99%的逻辑是相同的。

然后我有一个PluginManager,它也是一个抽象类,有2个扩展它的实现(ServiceManagerChannelManager),它们是包装器,自定义日志记录和更方便的构造函数。

我遇到的麻烦是,在我的PluginManager中必须能够实例化ServiceClassLoaderChannelClassLoader的新类加载器类型。我试图避免让我的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
    }
}

3 个答案:

答案 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设计模式。