我继承了一个特殊的单例类层次结构,其声明总结如下(有更多的实现 - 我只是展示了用于演示问题的最小集合)。它对我来说闻起来很高,最重要的是因为单例是从中继承而来的,以及基类中instance
的方式在子类的静态初始化器中覆盖了它的值。
如果所有实现都在foo.common
父包中,我会考虑从它们中删除instance
成员和getInstance()
方法,使类及其构造函数包本地化,并且在foo.common
中创建一个公共工厂类,创建每个工厂的单个实例,在内部保留每个单个实例(按{是IReadOnly
或IReadWrite
的实现划分)并提供一些公共查找方法,基于某些枚举,它会将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
}
答案 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容器或类似的框架。