如何重构单个类的层次结构,其中每个类都有一个getInstance()方法?

时间:2012-05-04 04:37:48

标签: java inheritance refactoring singleton

我继承了一个特殊的单例类层次结构,其声明总结如下(有更多的实现 - 我只是展示了用于演示问题的最小集合)。它对我来说闻起来很高,最重要的是因为单例是从中继承而来的,以及基类中instance的方式在子类的静态初始化器中覆盖了它的值。

如果所有实现都在foo.common父包中,我会考虑从它们中删除instance成员和getInstance()方法,使类及其构造函数包本地化,并且在foo.common中创建一个公共工厂类,创建每个工厂的单个实例,在内部保留每个单个实例(按{是IReadOnlyIReadWrite的实现划分)并提供一些公共查找方法,基于某些枚举,它会将ask-for实现作为接口类型返回。

但是实现可以在foo.common之外,并且foo.common不允许依赖于此类“更具体”的包,因为foo.common旨在用于一堆应用程序通用的内容。所以简单的事情是无法做到的。那么呢?

第一个界面:

package foo.common.config;
public interface IReadOnly
{
    void load();
    String getVal(String key);
}

第二界面:

package foo.common.config;
public interface IReadWrite extends IReadOnly
{
    void save();
    void setVal(String key, String value);
}

首次实施:

package foo.common.config;
public class ReadOnlyImpl implements IReadOnly
{
    protected static IReadOnly instance;

    static {
        instance = new ReadOnlyImpl();
    }

    public static IReadOnly getInstance() {
        return instance;
    }

    protected ReadOnlyImpl() {}

    // implement methods in IReadOnly
}

第二次实施

package foo.common.config;
public class ReadWriteImpl extends ReadOnlyImpl implements IReadWrite
{
    static {
        instance = new ReadWriteImpl();
    }

    public static IReadWrite getInstance() {
        return (IReadWrite) instance;
    }

    protected ReadWriteImpl() {
        super();
    }

    // Implement methods in IReadWrite
}

第三次实施:

// While things in this package can depend
// on things in foo.common, nothing in 
// foo.common is allowed to depend on this package.
package foo.apps.someapp;
public class MoreSpecificReadWriteImpl extends ReadWriteImpl
{
    static {
        instance = new MoreSpecificReadWriteImpl();
    }

    public static IReadWrite getInstance() {
        return (IReadWrite) instance;
    }

    protected MoreSpecificReadWrite() {
        super();
    }

    // Override superclass methods to do something specific
}

1 个答案:

答案 0 :(得分:1)

将软件包foo.apps.someapp放在一边,软件包foo.common.config的设计是错误的。

IReadOnly o1=ReadOnlyImpl.getInstance(); // ok, returns ReadOnlyImpl
...
ReadWrite o2=ReadWriteImpl.getInstance(); // ok, returns ReadWriteImpl 
...
IReadOnly o3=ReadOnlyImpl.getInstance(); // bad, returns ReadWriteImpl, the same as o2.

原因是所有类都使用相同的静态变量ReadOnlyImpl.instance。我会在所有类中使用单独的变量,包括MoreSpecificReadWriteImpl。如果这不适合,那么考虑使用Spring容器或类似的框架。