이펙티브 자바, private 생성자나 열거 타입으로 싱글턴임을 보장하라
싱글턴?
- 싱글턴이란 인스턴스를 오직 하나만 생성할 수 있는 클래스를 말한다.
필드 싱글턴
- static final로 유일함을 보장한다.
- 필드에서 직접 객체를 가져온다.
public class SingletonV1 {
// static final 이므로 메모리에서의 유일함을 보장한다. 쓰레드로부터 안전하다.
public static final SingletonV1 Instance = new SingletonV1();
// 리플렉션의 경우 싱글턴임에도 불구하고 객체 생성 가능하다. 아래의 에러를 통해 원천적으로 싱글턴의 재생성을 막는다.
private SingletonV1() {
throw new AssertionError();
}
}
정적 팩터리 싱글턴
- getInstance()를 통해 객체를 가져온다. 매서드 명을 명시할 수 있고, 매개변수나 코드를 구현할 수 있어서 필드 싱글턴보다 훨씬 유연하다.
public class SingletonV2Factory {
private static final SingletonV2Factory INSTANCE = new SingletonV2Factory();
// 팩토리 형태로 인스턴스를 전달한다.
// 이전의 방식보다 유연하다. supplier 등 사용 가능하다. 여러 방식으로 조작 가능하다.
public static SingletonV2Factory getInstance() {
return INSTANCE;
}
}
열거 타입
- 열거 타입은 enum 하나 마다 클래스를 생성하며, 이는 싱글턴을 보장한다.
public enum SingletonV3Enum {
INSTANCE
}
싱글턴과 스프링 빈 스코프 싱글턴? (아래부터는 사실 사담이다)
- 싱글턴은 유일한 객체를 보장하는 방식이다.
- 스프링이 IOC나 DI를 할 때, 마찬가지로 모든 빈에 대하여 유일함을 보장한다. 나는 이것이 일종의 싱글턴이라 이해했다. 싱글턴과 DI는 유사한 것으로 이해했다.
- 하지만 DI에게 있어서 싱글톤은 그저 스코프의 설정 값 중 하나이다. DI의 스코프는 싱글턴이 값이며 이는 유일한 빈을 보장한다. 프로토타입으로도 설정할 수 있는데, 이는 해당 객체를 사용할 때마다 계속 새로운 객체를 생성함을 의미한다.
- DI를 설명함에 있어 그것의 의미를 유일한 빈을 보장함에 있다로 한정할 수 없다. 다양한 컴퍼넌트가 하나의 어플리케이션으로 구성될 때, 자원과 의존성을 효율적이고 유지보수하기 쉽게 구현하는 기술을 DI라고 한다. 개발자 입장에서는 복잡한 의존성에 대하여 어너테이션이나 XML 명세서를 통해 외부에서 설정하고 쉽게 할 수 있도록 만드는 기술로서 이해해야 한다.
- 이 부분에 대해서는 좀 더 지식의 수준을 높혀서 차후 깊이를 더하겠다.