有时我需要只在应用程序生命周期中实例化一次的类。使它们成为单例是不好的,因为这会使单元测试变得有问题。

但是,由于在我的应用程序的生命周期中应该只有一个此类对象的实例,因此在应用程序运行时将此类对象实例化两次是错误的。

因此,我希望我的应用在其生命周期中一旦检测到该对象被实例化两次,同时在单元测试中仍允许该对象的多个实例化,则立即引发异常。

我认为这不是一个不合理的要求:如果在应用程序的一个生命周期中仅应创建一个这样的对象,则抛出异常似乎是正确的选择。

这是我在做什么:

/**
 * 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。

我的问题很简单:这有意义吗,我应该如何实现呢?

最佳答案

如果您的设计需要单例,那么最好不要使用单例,而要尝试一些复杂的事情。

例如,如果您在单元测试单例中遇到的麻烦是要模拟一个实例,那么我将创建一个可实例化的轻量级代理,该代理提供与单例相同的接口。

代理应该没有逻辑-它应该只将调用映射到单例。

然后,您可以在测试中使用它,并使代码库保持单例不变。轻量级代理可以保留在测试套件中,而不能发布。

07-24 09:33