Singleton Pattern
Singleton Pattern은 클래스의 인스턴스가 하나이면서 해당 인스턴스에 대해 전역적으로 접근할 수 있도록 하는 디자인 패턴입니다.
설정이나 관리를 위한 어떠한 역할을 수행하는 인스턴스가 단 하나만 존재해서 관리하도록 하는 등에 사용됩니다.
장점
- 클래스에 인스턴스가 하나만 있음을 확인, 보증할 수 있습니다.
- 다른 클래스의 인스턴스들이 싱글톤 인스턴스에 접근하기 쉽습니다.
- 메모리 영역에 할당되는 인스턴스가 하나이므로 *메모리를 낭비하지 않을 수 있습니다.
단점
- 싱글톤 인스턴스가 전역적인 접근을 처리하다 보면 다른 클래스 인스턴스와 결합도가 높아져 단일 책임 원칙을 위반할 수 있습니다.
- 멀티 쓰레드 환경에서 동기화 처리를 하지 않을 경우 다중 인스턴스가 생성되는 등의 문제가 발생할 수 있습니다.
- 많은 테스트 프레임워크가 객체를 생성할 때 상속에 의존하기 때문에 싱글톤 인스턴스의 단위 테스트에 어려움이 있을 수 있습니다.
구현 방법
- 싱글톤 인스턴스를 저장하기 위한 private static 필드를 추가합니다.
- 싱글톤 인스턴스를 반환하기 위한 public static 메소드를 추가합니다.
- 인스턴스를 반환하기 전 필드가 null 인지 체크하여 없으면 생성해서 넣어주고, 있으면 기존 인스턴스를 반환합니다.
- 생성자를 private로 만듭니다.
- 단일 쓰레드, 멀티 쓰레드 등에 맞게 적용합니다.
기본 예제
Lazy Initialization 방법의 예제입니다.
public class Singleton {
private static Singleton instance;
private Singleton() {
// ...
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
메소드 동기화
멀티 쓰레드 환경에서 Critical Section으로 인해 인스턴스가 중복 생성될 수 있는 것을 방지해보자 !
public class Singleton {
private static Singleton instance;
private Singleton() {
// ...
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
중복 생성은 막았지만 메소드 호출이 동기화되는 경우 성능에 영향을 미칠 수 있습니다.
Double-Checked Locking Pattern (DCLP)
메소드에 동기화를 하지 않고 인스턴스가 없을 때 생성하는 부분만 동기화를 걸어주면 조금 더 효율적으로 동작하겠죠?
public class Singleton {
private static volatile Singleton instance;
private Singleton() {
// ...
}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
처음 생성할 때 말고는 synchronized에 걸리지 않기 때문에 성능이 조금 더 개선됐습니다 🔥
그러나 동기화 문제에 대한 코드가 추가되면서 복잡도가 올라갈 수 있죠.
Bill Pugh Solution
Bill Pugh(윌리엄 퓨) Singleton, Static Holder Singleton Pattern, Initialization-on-demand Holder Idiom라고 불립니다.
이름에서 알 수 있듯이 Holder라는 개념이 등장합니다. 이는 클래스 안의 클래스입니다.
이 방법은 JVM의 클래스 초기화 특성을 활용하여 Thread Safe가 보장되도록 합니다.
public class Singleton {
private Singleton() {
// ...
}
private static class SingletonHolder {
public static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
참고
'개발 > Design Pattern' 카테고리의 다른 글
[Design Pattern] 추상 팩토리 패턴 (Abstract Factory) (0) | 2022.10.26 |
---|---|
[Design Pattern] 팩토리 메서드 패턴 (Factory Method) (0) | 2022.10.25 |
[Design Pattern] 어댑터 패턴 (Adapter) (0) | 2022.10.24 |
[Design Pattern] 데코레이터 패턴 (Decorator) (0) | 2022.10.24 |
[Design Pattern] 프록시 패턴 (Proxy) (0) | 2022.10.20 |