簡體   English   中英

在不使用靜態方法的情況下制作類單例

[英]Making a class singleton without using static method

我需要創建一個單例類而不保留靜態方法。

我怎樣才能做到這一點?

用一個實例創建一個枚舉

enum Singleton {
    INSTANCE;

    private Field field = VALUE;
    public Value method(Arg arg) { /* some code */ }
}

// You can use
Value v = Singleton.INSTANCE.method(arg);

編輯: Java 枚舉教程向您展示了如何向枚舉添加字段和方法。


順便說一句:通常當您可以使用單例時,您實際上並不需要單例,因為實用程序類會做同樣的事情。 更短的版本只是

enum Utility {;
    private static Field field = VALUE;
    public static Value method(Arg arg) { /* some code */ }
}

// You can use
Value v = Utility.method(arg);

單例的用處在於它們實現接口時。 這對於使用依賴注入進行測試特別有用。 (在單元測試中使用單例或實用程序類替換的弱點之一)

例如

interface TimeService {
    public long currentTimeMS();
}

// used when running the program in production.
enum VanillaTimeService implements TimeService {
    INSTANCE;
    public long currentTimeMS() { return System.currentTimeMS(); }
}

// used in testing.
class FixedTimeService implements TimeService {
    private long currentTimeMS = 0;
    public void currentTimeMS(long currentTimeMS) { this.currentTimeMS = currentTimeMS; }
    public long currentTimeMS() { return currentTimeMS; }
}

如您所見,如果您的代碼在任何地方都使用 TimeService,您可以注入VanillaTimeService.INSTANCEnew FixedTimeService() ,您可以在其中從外部控制時間,即每次運行測試時您的時間戳都相同。

簡而言之,如果您不需要單例來實現接口,那么您可能只需要一個實用程序類。

public class Singleton {
    public static final Singleton instance = new Singleton();
    private Singleton() {}
    public void foo() {}
}

然后使用

Singleton.instance.foo();

另一種方法是單例持有者習慣用法,它提供按需初始化:

public class Something {
        private Something() {
        }
 
        private static class LazyHolder {
                public static final Something INSTANCE = new Something();
        }
 
        public static Something getInstance() {
                return LazyHolder.INSTANCE;
        }
}

請注意,應該盡可能避免像這樣的獨立單例,因為它會提升全局狀態,導致難以進行單元測試的代碼,並且依賴於單個類加載器上下文來列舉一些可能的缺點。

按照“Effective Java”第二版中的 Joshua Bloch 枚舉方法進行操作。 這是創建單身人士的最佳方式。

我不明白為什么會出現這么多。 單例不是一種名譽掃地的設計模式嗎? 今天,GoF 將把它投票離開該島。

您可以使用 IoC 容器之一(例如Google Guice )並將您的類用作單例(急切或懶惰 - 這取決於您的需要)。 由於實例化是由 IoC 框架控制的,因此它既簡單又靈活——例如,如果您稍后決定讓您的類不是單例,則不需要任何代碼更改。

使用對象工廠,從這個工廠獲取你的單例對象。

ObjectFactory factory;
....
MySingletonObject obj = factory.getInstance(MySingletonObject.class);

當然,有很多框架可以幫助您實現這一目標。 spring 框架是一個流行的選擇。

從構造函數中,您需要檢查某處是否已經存在該類的實例。 因此,您需要在靜態變量或類中存儲對單例實例的引用。 然后在單例的構造函數中,我總是會檢查是否存在單例類的現有實例。 如果是,我不會做任何事情,否則我會創建它並設置參考。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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