繁体   English   中英

将抽象类详细信息与扩展实现分离

[英]Decouple abstract class details from extended implementations

我有一个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
    }
}

您会错过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> 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();
    }
}

这实现了工厂方法设计模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM