有时我需要只在应用程序生命周期中实例化一次的类。使它们成为单例是不好的,因为这会使单元测试变得有问题。
但是,由于在我的应用程序的生命周期中应该只有一个此类对象的实例,因此在应用程序运行时将此类对象实例化两次是错误的。
因此,我希望我的应用在其生命周期中一旦检测到该对象被实例化两次,同时在单元测试中仍允许该对象的多个实例化,则立即引发异常。
我认为这不是一个不合理的要求:如果在应用程序的一个生命周期中仅应创建一个这样的对象,则抛出异常似乎是正确的选择。
这是我在做什么:
/**
* 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。
我的问题很简单:这有意义吗,我应该如何实现呢?
最佳答案
如果您的设计需要单例,那么最好不要使用单例,而要尝试一些复杂的事情。
例如,如果您在单元测试单例中遇到的麻烦是要模拟一个实例,那么我将创建一个可实例化的轻量级代理,该代理提供与单例相同的接口。
代理应该没有逻辑-它应该只将调用映射到单例。
然后,您可以在测试中使用它,并使代码库保持单例不变。轻量级代理可以保留在测试套件中,而不能发布。