싱글턴 패턴은 클래스 인스턴스를 하나만 만들고, 그 인스턴스로의 전역 접근을 제공하는 방법입니다.
싱글턴? 단순히 객체 인스턴스 1개 만드는 방법 아니야?
맞습니다. 하지만 하나만 있어도 충분히 잘 돌아가는 객체가 많습니다.
스레드 풀, 캐시, 대화상자, 사용자 설정, 등등 이런 객체들은 1개여야 정상적으로 작동할 수 있죠.
정적 변수를 쓰면 되는 것 아닌가요?
싱글턴 패턴은 특정 클래스에 객체 인스턴스가 하나만 만들어지도록 해 주는 패턴입니다.
전역 변수에 어떤 단점이 있나요?
전역 변수에 객체를 대입하면 애플리케이션이 시작할 때 객체가 생성됩니다. 리소스가 큰 객체이지만, 만약 사용하지 않게 되면 자원만 잡아먹는 객체를 생성하게 된 꼴 입니다. -> 그러면 싱글턴 패턴은 필요할때 생성하는건가?
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
이렇게 하면 getInstance가 호출되기 전까지는 인스턴스를 생성하지 않을 수 있어요.
이러한 방법을 게으른 인스턴스 생성(lazy instantiation)이라고 부른답니다.
멀티스레드 환경에서 싱글턴이 돌아가게 만들려면 어떻게 할까요?
1. synchronized getInsatnce() 를 사용한다.
2. 인스턴스가 필요할 때 생성하지 말고 처음부터 만듭니다.
3. DLC(Double-Checked Locking)을 사용해서 인스턴스가 생성돼 있는지 확인 후 생성되어 있지 않았을 경우에만 동기화할 수 있습니다. 이렇게 되면 처음에만 동기화, 그 이후에는 동기화가 필요 없죠.
public class DlcSingleton {
private volatile static DlcSingleton uniqueInstance;
private DlcSingleton() {
}
public static DlcSingleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new DlcSingleton();
}
}
}
return uniqueInstance;
}
}
모든 메서드와 변수가 static으로 선언된 클래스를 만들어도 되지 않나요?
필요한 모든 내용이 클래스에 다 들어 있고, 복잡한 초기화가 필요 없는 경우에만 그 방법을 쓸 수 있습니다.
클래스 로더와 관련된 문제는 없나요?
클래스로더가 여러 개일때 따로 클래스 로더를 지정해주지 않으면 문제가 생길 수 있습니다.
리플렉션, 직렬화, 역직렬화 문제는 없나요?
있습니다. 조심히 사용해야 해요.
enum을 사용하면 싱글턴의 여러 문제점을 해결할 수 있는 것 아닌가요?
맞습니다. 지금까지의 getInstance() 메서드 구현 과정은 싱글턴 원리를 위한 학습이었습니다.
출처
에릭 프리먼, 엘리자베스 롭슨, 케이시 시에라, 버트 베이츠. 『헤드퍼스트 디자인패턴 개정판』. 한빛미디어, 2022
'Design Pattern' 카테고리의 다른 글
어댑터 패턴 (Adapter Pattern) (0) | 2023.10.23 |
---|---|
커맨드 패턴 (Command Pattern) (0) | 2023.09.27 |
팩토리 패턴(Factory Pattern) (0) | 2023.09.14 |
데코레이터 패턴(Decorator Pattern) (2) | 2023.09.11 |
옵저버 패턴(Observer Pattern) (0) | 2023.09.07 |