簡體   English   中英

Java中的Singleton類如何處理這種情況?

[英]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方法,所以可以防止外部更改。

有什么想法嗎?

我認為您想要一個帶有論點的辛格爾頓。 這應該解釋一下:

Java中帶有參數的Singleton

由於此類是Singleton,因此名稱實際上不應更改太多。 我建議只是將其作為類中的一個常數。 如果在不同情況下執行該程序時名稱可能更改,請參見下面的解決方案2。

解決方案1:

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;
    }
}

解決方案2:

如果您確實要設置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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM