Sim*_*mon 23 java inheritance singleton abstract-class classloader
这是我的示例抽象单例类:
public abstract class A {
protected static A instance;
public static A getInstance() {
return instance;
}
//...rest of my abstract methods...
}
Run Code Online (Sandbox Code Playgroud)
以下是具体实施:
public class B extends A {
private B() { }
static {
instance = new B();
}
//...implementations of my abstract methods...
}
Run Code Online (Sandbox Code Playgroud)
不幸的是我无法在B类中获取静态代码来执行,因此实例变量永远不会被设置.我试过这个:
Class c = B.class;
A.getInstance() - returns null;
Run Code Online (Sandbox Code Playgroud)
还有这个
ClassLoader.getSystemClassLoader().loadClass("B");
A.getInstance() - return null;
Run Code Online (Sandbox Code Playgroud)
在eclipse调试器中运行这两个,静态代码永远不会被执行.我可以找到执行静态代码的唯一方法是将B的构造函数的可访问性更改为public,并调用它.
我在Ubuntu 32bit上使用sun-java6-jre来运行这些测试.
从您的帖子开始,即使没有明确说明,听起来您希望抽象类扮演两个不同的角色.角色是:
另外,您希望服务在整个类的系列中是单例强制执行'singletoness',由于某种原因,它不足以缓存服务实例.
这可以.
有人会说它闻起来非常糟糕,因为"违反了关注点的分离","单身人士和单位测试并不能很好地结合在一起".
其他人会说这是好的,因为你赋予了在家庭中实例化正确的孩子的责任,并且整体上也暴露了更流畅的界面,因为你不需要调解工厂,除了暴露静态方法之外什么也不做.
有什么问题是你希望孩子们负责选择父工厂方法应该返回什么实现.这在设计方面是错误的,因为你委托给所有孩子,可以简单地将其推入并集中到抽象超类中,并且它还表明你正在混合使用在不同上下文中使用的模式,抽象工厂(父级决定什么类的类)客户将获得)和工厂方法(儿童工厂选择客户将获得的).
工厂方法不仅不是必需的,而且也不可能与工厂方法一起使用,因为它集中于实现或覆盖"实例"方法.对于静态方法,也没有构造函数的覆盖.
因此,回到一个抽象单例的初始好或坏的想法,选择要暴露哪些行为有几种方法来解决最初的问题,一个可能是以下,看起来很糟糕,但我想接近你正在寻找的:
public abstract class A{
public static A getInstance(...){
if (...)
return B.getInstance();
return C.getInstance();
}
public abstract void doSomething();
public abstract void doSomethingElse();
}
public class B extends A{
private static B instance=new B();
private B(){
}
public static B getInstance(){
return instance;
}
public void doSomething(){
...
}
...
}
//do similarly for class C
Run Code Online (Sandbox Code Playgroud)
父母也可以使用反思.
更多测试友好和扩展友好的解决方案只是让孩子不是单身,而是打包成一些内部包,你将其记录为"私人"和抽象的父,可以暴露"单身模仿"静态getInstance()并将缓存孩子强制客户端始终获得相同服务实例的实例.