簡體   English   中英

如何實現近單身?

[英]How to implement a near-singleton?

我有時需要只在應用程序生命周期中實例化一次的類。 讓他們成為單身人士是不好的,因為單元測試變得有問題。

但是,因為在我的應用程序的生命周期中應該存在這樣的對象的唯一實例,所以在應用程序運行時將這樣的對象實例化兩次將是錯誤的。

因此,我希望我的應用程序在其生命周期中檢測到這樣的對象被實例化兩次, 同時仍然允許在單元測試時對這樣的對象進行多次實例化時拋出異常。

我認為這不是一個不合理的要求:如果在應用程序的一個生命周期中只應創建一個這樣的對象,那么拋出異常似乎是正確的事情。

這是我正在做的事情:

/**
 * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
 * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
 * document are to be interpreted as described in RFC 2119.
 *
 * You MUST NOT instantiate this class more than once during the application's
 * lifecycle.  If you try to do so, an exception SHALL be thrown.
 *
 * You SHOULD be able to instantiate this class more than once when unit
 * testing.
 *
 * 
 */
public class LifeCycle {

    private static final AtomicInteger cnt = new AtomicInteger( 0 );

    @NotNull
    public static LifeCycle getNewLifeCycle() {
        if ( cnt.incrementAndGet() > 1 && App.isRealApp() ) {
            throw new IllegalStateException("Class is already instantiated");
        }
        return new LifeCycle();
    }

}

其中App.isRealApp()在我進行單元測試時總是返回false ,並且在真實應用程序運行時始終為true

我的問題很簡單:它是否有意義,我應該如何實現這一點?

如果你的設計需要單身,那么你最好選擇單身而不是嘗試復雜的東西。

例如,如果您在單元測試單例中遇到的問題是獲取模擬實例,那么我將創建一個可實例化的輕量級代理,它提供與您的單例相同的接口。

代理應該沒有邏輯 - 它應該只是將調用映射到單例。

然后,您可以在測試中使用它,並使代碼庫保持單一完整。 輕量級代理仍然是測試套件的一部分,而不是發布。

一種解決方案是使用像Spring這樣的依賴注入框架。

應用程序配置將指定單例實例,但您的測試用例仍然可以創建按需實例並手動注入它們。

有關更多信息,請訪問: http//static.springsource.org/spring/docs/2.5.x/reference/testing.html

另一種方法是,如果您已經在代碼中添加了靜態單例引用,則將Singleton.getInstance()方法轉換為真正的工廠,使用系統屬性來控制其行為。 這個系統屬性可以像一個標志一樣簡單,表示測試正在進行中,或者與另一個用作真實工廠的類的名稱一樣復雜(類似於JDK對DocumentBuilderFactory )。

因此,我希望我的應用程序在其生命周期中檢測到這樣的對象被實例化兩次后立即拋出異常

這就是辛格爾頓所執行的。

同時仍然允許在單元測試時對這樣的對象進行多次實例化。

您可以使用@ com.dp4j.Singleton強制執行此操作

這就是Reflection API允許的內容。

您可以直接使用Reflection API,也可以讓dp4j為您注入。 在這里,您將找到兩者的代碼。

暫無
暫無

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

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