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



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

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

遇到的麻烦是,以我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();
    }
}

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

最新更新