싱글톤 패턴(Singleton Pattern)
- 어떤 클래스가 단 하나의 인스턴스만을 가지도록 하는 디자인 패턴
- 용도
- 리소스 공유 : 여러 부분에서 하나의 인스턴스를 공유해야 하는 경우 ex) 데이터베이스 연결, 네트워크 연결, 로깅 등
- 전역 객체 : 전역적으로 접근해야 하는 설정 정보나 상태 정보 관리
- 객체 생성 제어 : 객체 생성을 제한하고 특정 클래스의 인스턴스가 항상 하나만 생성되도록 보장
- 사용 방법
- 생성자 비공개 : 해당 클래스의 생성자를 private으로 선언하여 외부에서 객체를 직접 생성하는 것을 막는다.
- 정적 메서드로 인스턴스 제공 : 클래스 내부에 정적(static) 메서드(getInstance())를 생성하여 해당 메서드를 통해서만 객체 인스턴스를 얻을 수 있도록 한다.
- 장점
- 자원 공유와 메모리 절약 : 하나의 인스턴스를 공유하기 때문에 메모리 낭비를 줄이고 자원을 효율적으로 활용할 수 있다.
- 전역적인 접근 : 어디서든 해당 인스턴스에 접근할 수 있어서 다른 클래스의 인스턴스들이 데이터를 공유하는 것이 가능하다.
- 단점
- 단일 책임 원칙 위반 : 싱글톤 클래스는 객체 생성과 관리의 역할을 가지므로 단일 책임 원칙(SRP)을 위반할 수 있다.
- 테스트 어려움 : 싱글톤 객체는 다른 클래스에 의존성을 갖고 있기 때문에 테스트가 어려울 수 있다.
- 멀티 스레드 환경에서 동기화 처리를 하지 않으면, 인스턴스가 2개 생성될 수 있다.
- 반드시 싱글톤이 필요한 상황이 아니면 지양하는 것이 좋다.
싱글톤 구현
1. Lazy Initialization (게으른 초기화)
인스턴스가 필요한 시점에 생성하는 방법으로, 멀티스레드 환경에서 안전하게 구현하려면 'synchronized' 키워드를 사용하여 동기화해야 한다. 이 방법은 처음에만 동기화되므로 성능저하가 있을 수 있다.
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
2. Lazy Initialization + Double-checked Locking
Double-checked Locking은 인스턴스가 이미 생성되었는지 확인한 후 동기화 블록에 들어가는 방식으로 성능 향상을 위해 사용된다. 'volatile' 키워드는 인스턴스의 변경 사항을 다른 스레드에 즉시 반영하도록 보장한다.
public class DoubleCheckedSingleton {
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {
}
public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
3. Initialization on demand hodler idiom (holder에 의한 초기화)
클래스 로더의 초기화 메커니즘을 이용하여 멀티스레드 환경에서 안전한 싱글톤을 만드는 방법으로, 내부 클래스를 사용하여 구현된다.
이 방법은 클래스 로더에 의해 내부 클래스가 로드되는 시점에 인스턴스가 생성되므로 Lazy Initialization과 달리 동기화가 필요하지 않다. Holder 클래스는 JVM에 의해 초기화되는 동안 다중 스레드에 안전하게 인스턴스를 생성한다.
public class HolderSingleton {
private HolderSingleton() {
}
private static class SingletonHolder {
private static final HolderSingleton instance = new HolderSingleton();
}
public static HolderSingleton getInstance() {
return SingletonHolder.instance;
}
}
[참고] https://gyoogle.dev/blog/design-pattern/Singleton%20Pattern.html
'Computer Science > Design Pattern' 카테고리의 다른 글
[Design Pattern] 컴포지트 패턴 (Composite Pattern) (0) | 2023.10.08 |
---|---|
[Design Pattern] 팩토리 메소드 패턴 (Factory Method Pattern) (0) | 2023.09.23 |
[Design Pattern] 템플릿 메소드 패턴 (Template Method Pattern) (0) | 2023.09.23 |
[Design Pattern] 어댑터 패턴 (Adapter Pattern) (0) | 2023.09.22 |
[Design Pattern] SOLID (0) | 2023.09.14 |