我有一些用作单身人士的课程。它们共享一些基本功能,并从库中扩展相同的祖先,而库通常不会用作单例。
如果我将公共功能放在继承自共同祖先的基类中,我会得到一个实例化没有意义的类,所以我把它变成了抽象的。此外,因为这些类都被用作单例,所以它们都应该有一个init()和一个getInstance()方法,它们都是静态的。所有的建设者当然都是非公开的。
现在,由于static
是抽象方法的非法修饰符,因此以下方法不起作用,尽管这正是我想要的:
class Base extends LibraryClass {
protected Base() {
// ... constructor
}
// ... common methods
// ILLEGAL!
public static abstract void init();
public static abstract <T extends Base>T getInstance();
}
class A extends Base {
private static A _INSTANCE;
private A() {
super();
}
public static void init() {
_INSTANCE = new A();
}
public static A getInstance() {
return _INSTANCE;
}
}
我可以省略基类中的非法行并完成它。但是,我如何表达Base 的每个孩子必须拥有这些方法?
答案 0 :(得分:14)
这在Java中是不可能的。 static
方法的存在无法实施;既不是abstract
也不是interface
。
我的解决方案是以某种方式使用IoC:我为单身人士创建了一个工厂类。它会将单身人士保存在地图中。关键是班级。这样,我可以说:
A singleton = Factory.create (A.class);
这种设计的主要优点:我可以创建一个Factory.replace()
方法,其中测试用例可以覆盖单例。
答案 1 :(得分:3)
处理将单例语义添加到可能不方便正确添加语义的类的常用方法是在包装类中实现单例功能。例如:
public class UsefulThing {
}
public final class SingletonOfUsefulThing {
private static UsefulThing instance;
private SingletonOfUsefulThing() {}
public UsefulThing getInstance() {
if (instance == null) {
instance = new UsefulThing();
}
return instance;
}
}
这允许您为类提供一些主要的单例优势,而没有一些后果,直接强制您在类中实现单例语义并允许一些空间来更改类的特定类型重新暴露为单身人士(例如,通过使用工厂来创建实例,而不是new
。
答案 2 :(得分:2)
您无法表达子类具有特定的静态方法。
实际上应该没有必要这样做,因为静态方法只会直接在子类(在您的示例中为A.init()
和A.getInstance()
)上调用,并且永远不会通过对基类的引用class(即静态方法不支持多态)。
答案 3 :(得分:1)
为什么不一直走,让你的工厂(在基类中)传入一个参数,指出你希望它返回哪个子类。这样做有很多好处,而且缺点很少。
您尝试这样做的方式并没有多大意义,因为静态方法不像普通方法那样处理继承。