[英]How to handle this situation for a Singleton class in Java?
我对如何在遵循Singleton模型的课程上进行以下操作有疑问。
我有这个原始的Singleton课程:
public class ThreadsManager {
// I can have only one instance:
private final static ThreadsManager instance = new ThreadsManager();
// Private constructor:
private ThreadsManager() {
}
public static ThreadsManager getInstance(){
return instance;
}
}
好的,这项工作很好,但是现在我必须对其进行修改,添加一个新属性(名为userName的字符串),该属性必须在构建单例对象时进行初始化,并且以后无法更改
所以我正在尝试做这样的事情:
public class ThreadsManager {
private final static ThreadsManager instance = new ThreadsManager();
private final static String userName;
private ThreadsManager() {
}
public static ThreadsManager getInstance(String user){
userName = user;
return instance;
}
}
所以我试图添加新的String userName变量,该变量是静态的 (对于该类一次)和最终的 (无法在第二次更改)
我的问题是Eclips将以下行标记为错误:
1) 私有最终静态String userName; 对我说:
The blank final field userName may not have been initialized
似乎该字段将被初始化(我可以将其初始化为null,但是由于它是最终的...我以后不能在构造函数中初始化)
2) userName =用户; 对我说:
The final field ThreadsManager.userName cannot be assigned
那么解决这种情况的最佳解决方案是什么?
如果我从userName变量定义中删除最终值 ,在我看来效果很好,但是可以更改此值,但是也许我根本无法为该字段提供setter方法,所以可以防止外部更改。
有什么想法吗?
我认为您想要一个带有论点的辛格尔顿。 这应该解释一下:
由于此类是Singleton,因此名称实际上不应更改太多。 我建议只是将其作为类中的一个常数。 如果在不同情况下执行该程序时名称可能更改,请参见下面的解决方案2。
public class ThreadsManager
{
private final static ThreadsManager instance = new ThreadsManager();
private String userName;
private ThreadsManager()
{
final String name = "Name";
userName = name;
}
public static synchronized ThreadsManager getInstance(String user)
{
return instance;
}
}
如果您确实要设置Singleton的名称,并且每次执行程序时,名称可能会有所不同。 只需添加此方法:
private String userName = null;
// Can only be set after Singleton is created and when userName is null.
public void setName(String n)
{
if(userName == null)
userName = n;
}
不要让您的getInstance()
方法具有参数, 这是一个错误的设计 。 每次有人或您尝试从您的类中获取实例时,他们/您都必须提供一个与99%的时间无关的参数。
如果您想要该类的实例的多个状态,则不会是单例,
您可以创建一个以user
为键的Object的缓存,因此对于要求相同状态的对象仍然是单例
private final Map<String, ThreadsManager> instanceCache = Collections.synchronizedMap<String, ThreadsManager>();
此外,如果您有很多此类的状态,请确保您不会泄漏内存
您可以使用嵌套类来实现。
public class ThreadsManager {
private static String userName;
private ThreadsManager() {
}
public static ThreadsManager getInstance(String user){
if (userName == null)
userName = user;
// the holder's instance is only initialised at this point,
// after userName is set.
return Holder.instance;
}
static class Holder {
private final static ThreadsManager instance = new ThreadsManager();
}
}
首先:私有最终静态字符串userName只能在私有构造函数内部或在定义期间初始化。
其次,您可能最终得到一个null实例,因此您可能会执行以下操作:
public class ThreadsManager {
private final static ThreadsManager instance = new ThreadsManager();
private String userName;
private ThreadsManager() {
}
private ThreadsManager(String user) {
userName = user;
}
public static ThreadsManager getInstance(String user){
if(instance == null) {
instance = new ThreadsManager(user);
} else {
Logger.getInstance().logWarning("User has already been set. Will continue with user ["+username+"].);
}
return instance;
}
}
处理如何处理第二个用户名的处理需要一些思考。 总体上,您应该尝试使getInstance()方法参数保持空闲状态,因为它会导致上述问题。
怎么样
public class ThreadsManager {
private final static ThreadsManager instance = new ThreadsManager();
private static String userName;
public static synchronized ThreadsManager getInstance( String user ) {
if ( username == null ) { userName = user; }
return instance;
}
这样可以确保仅在第一次设置userName
。
但是,单身人士在随后的getInstance()
上采用被忽略的参数可能会造成非常混乱的语义,具体取决于您的用例,甚至可能出现竞态条件。
干杯,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.