3 回答

TA贡献1851条经验 获得超4个赞
我会很清楚地指出:具有参数的单例不是单例。
根据定义,单例是您希望被实例化的对象不超过一次。如果您试图将参数提供给构造函数,那么单例的意义是什么?
您有两个选择。如果您希望用一些数据初始化单例,则可以在实例化之后用数据加载它,如下所示:
SingletonObj singleton = SingletonObj.getInstance();
singleton.init(paramA, paramB); // init the object with data
如果您的单例正在执行的操作是重复发生的,并且每次都使用不同的参数,则最好将这些参数传递给正在执行的main方法:
SingletonObj singleton = SingletonObj.getInstance();
singleton.doSomething(paramA, paramB); // pass parameters on execution
无论如何,实例化总是没有参数的。否则,您的单身人士将不是单身人士。

TA贡献2011条经验 获得超2个赞
我认为您需要像工厂这样的东西来实例化和重用各种参数的对象。可以通过使用同步对象HashMap或ConcurrentHashMap将参数(Integer例如)映射到“单个”可参数化类来实现。
尽管您可能会改用常规的非单例类(例如,需要10.000个不同参数化的单例)。
这是此类商店的示例:
public final class UsefulObjFactory {
private static Map<Integer, UsefulObj> store =
new HashMap<Integer, UsefulObj>();
public static final class UsefulObj {
private UsefulObj(int parameter) {
// init
}
public void someUsefulMethod() {
// some useful operation
}
}
public static UsefulObj get(int parameter) {
synchronized (store) {
UsefulObj result = store.get(parameter);
if (result == null) {
result = new UsefulObj(parameter);
store.put(parameter, result);
}
return result;
}
}
}
为了进一步推动它enum,尽管只允许使用固定数量的静态变体,但是Java 也可以视为(或用作)参数化的单例。
但是,如果您需要分布式1解决方案,请考虑一些横向缓存解决方案。例如:EHCache,Terracotta等。
1可能跨越多台计算机上的多个VM。

TA贡献1858条经验 获得超8个赞
您可以添加可配置的初始化方法,以将实例化与获取分开。
public class Singleton {
private static Singleton singleton = null;
private final int x;
private Singleton(int x) {
this.x = x;
}
public static Singleton getInstance() {
if(singleton == null) {
throw new AssertionError("You have to call init first");
}
return singleton;
}
public synchronized static Singleton init(int x) {
if (singleton != null)
{
// in my opinion this is optional, but for the purists it ensures
// that you only ever get the same instance when you call getInstance
throw new AssertionError("You already initialized me");
}
singleton = new Singleton(x);
return singleton;
}
}
然后,您可以调用Singleton.init(123)一次进行配置,例如在应用启动时。
添加回答
举报