Singleton 패턴은 다음 세 가지 원칙을 따른다.
- 인스턴스는 오직 한 개만 글로벌하게 접근
- private 생성자를 통해 클래스 내부에서만 인스턴스 생성 제어
- static 메서드를 통해 instance를 제공
방법 1) 가장 단순한 접근 방식
- thread safe하지 않다. -> instance가 2개가 생성될 수 있다.
public class Example {
private static Example instance;
private Example() {}
public static Example getInstance() {
if (instance == null) {
instance = new Example();
}
return instance;
}
}
방법 2) synchronized를 통해 임계 영역 적용(lock)
- but 성능 이슈
public class Example {
private static Example instance;
private Example() {}
public static synchronized Example getInstance() {
if (instance == null) {
instance = new Example();
}
return instance;
}
}
* class loading 후 초기화 단계는 synchronized를 적용하여 초기화 됨*
방법 3) Eager Initialization (즉시 초기화)
- class load 시점에 1번만 초기화 보장
- 만약 getinstance 호출 없이 다른 class 파일에서 import 않는 경우에도 Instance가 생성된다.
public class Example {
private static final Example instance = new Example();
private Example() {}
public static Example getInstance() {
return instance;
}
}
방법 4) Inner Static Class
- getInstance() 호출 전까지 객체 생성 안 함
- serialization/deserialization, reflection 기법을 사용하는 경우 single tone 보장 x
public class {
private Settings4() {}
private static class Settings4Holder {
private static final Settings4 INSTANCE = new Settings4();
}
public static Settings4 getInstance() {
return Settings4Holder.INSTANCE;
}
}
방법 5) enum
- 구현이 매우 쉽고, serialization/deserialization, reflection 상황에서도 안전하다.
- lazy loading 지원 x, 상속이 안되는 단점
public enum Singleton {
INSTANCE;
}