2010-12-23 5 views
5

때로는 응용 프로그램의 수명주기 동안 한 번만 인스턴스화해야하는 클래스가 필요합니다. 단위 테스트가 문제가되기 때문에 싱글 톤을 만드는 것은 나쁘다. 하나는 내 응용 프로그램의 수명주기 동안 이러한 객체의 인스턴스가 있어야거의 싱글 톤을 구현하는 방법은 무엇입니까?

하지만 여전히 때문에 응용 프로그램이를 실행 중일 때, 지금까지 두 번 을 같은 개체를 인스턴스화하는 것은 오류 일 것이다.

따라서 내 응용 프로그램이 해당 수명주기 동안 두 번 인스턴스화 된 것을 발견하면 즉시 예외를 throw하고 싶습니다. 단위 테스트 동안 이러한 개체의 여러 인스턴스화를 허용하는 중.

나는 그것이 무리한 요구하지 생각 : 응용 프로그램의 한주기 동안 단 하나의 개체를 생성 할 필요가있는 경우는 예외를 던지는 할 수있는 올바른 것처럼 보인다.

는 여기에 내가 뭘하는지입니다 : 내가 단위 테스트 항상 실제 응용 프로그램이 실행되는 사실있을 때 App.isRealApp은() 항상 거짓을 반환하여야한다

/** 
* 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(); 
    } 

} 

.

내 질문은 간단하다 : 그것은 의미가 않고 어떻게이를 구현 해야하는 건가요?

답변

9

당신의 디자인은 싱글이 필요한 경우, 다음 싱글이 아닌 복잡한 무언가를 시도 형편이 최고야.

예를 들어, 단위 테스트 싱글 톤에서 문제가 발생하면 인스턴스를 모의합니다. 예를 들어, 싱글 톤과 동일한 인터페이스를 제공하는 인스턴스 가능한 간단한 프록시를 만들 수 있습니다.

프록시는 어떤 논리가 없어야한다 - 그냥 싱글을 통해 전화를 매핑해야합니다.

그 다음은 테스트에 사용하고, 싱글 그대로와 코드베이스를 남길 수 있습니다. 경량 프록시는 테스트 스위트의 일부로 남아있을 수 있으며 릴리스되지 않습니다.

+1

+1, 나는 경량 프록시 아이디어를 좋아합니다! – NoozNooz42

+0

그것은 저에게 효과적입니다. 그리고 나는 코드베이스를 그대로 유지할 수 있다는 것을 의미했습니다. –

5

한 용액을 스프링처럼 의존성 주입기구를 사용하는 것이다.

응용 프로그램 구성은 싱글 톤 인스턴스를 지정하지만 테스트 사례는 필요에 따라 인스턴스를 만들고 수동으로 주입 할 수 있습니다. 자세한 내용은

: 이미 코드 전체에 뿌려 정적 싱글 참조를 가지고있는 경우에 http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

대안은, 동작을 제어하는 ​​시스템 속성을 사용하여, 진정한 공장으로 Singleton.getInstance() 방법을 변환하는 것입니다. 이 시스템 프로퍼티는 테스트가 진행 중임을 나타내는 플래그 또는 JDK가 DocumentBuilderFactory으로하는 것과 비슷한 실제 팩토리로 사용할 다른 클래스의 이름처럼 복잡 할 수 있습니다.

+0

@Anon : +1 너무 ... 나는 단위 테스트를 허용하면서 스프링을 싱글 톤 만 허용하도록 응용 프로그램 수준에서 구성 할 수 있다는 것이 매우 흥미 롭습니다. 멋지군, 나는 그것에 대해 읽을 것이다. – NoozNooz42

+0

Spring과 같은 복잡한 프레임 워크가 그렇게 단순한 문제에 복잡하지는 않습니까? 나는 그 대답이 아주 분명하다고 생각한다. 코드를 테스트하고 코드를 변경하여 테스트 할 수 있도록 테스트 코드를 작성해야합니다. – RoflcoptrException

+0

스프링은 약간은 있지만 인스턴스 생성을 제어하는 ​​팩토리는 기본적으로 리팩토링 부하가 너무 높지 않은 한이 목적을 위해 동일한 것이고 훨씬 더 가볍습니다. –

0

는 그러므로 나는 그런 물체가 싱글이 적용 무엇을 두 배

를 인스턴스화되고있는, 수명주기 동안 즉시 감지으로 예외를 던져 내 응용 프로그램을 싶습니다.

그러나 단위 테스팅 중에도 이러한 개체를 여러 번 인스턴스화 할 수 있습니다.

당신은 리플렉션 API가 있습니다 무엇 @com.dp4j.Singleton

에 이것을 적용 할 수 있습니다.

Reflection API를 직접 사용하거나 dp4j를 사용하여 삽입 할 수 있습니다. Here 코드를 찾을 수 있습니다.

관련 문제