해당 포스팅은 한빛 미디어 헤드퍼스트 디자인 패턴(에릭 프리먼, 엘리자베스 롭슨 저)를 통해 공부한 내용을 정리한 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
좋은 프로그래머는 자기 두뇌를 사용한다. 그러나 좋은 가이드라인은 모든 케이스를 고려해야만 하는 노력을 줄여준다.
(Francis Glassborow, 개발자)
Singleton Pattern 사용이유
먼저 singleton pattern 사용 이유를 먼저 설명하겠습니다.
- 하나만 있어도 충분히 돌아가는 또는 하나만 있어야 하는 객체에 사용
- Thread pool, Cache, Logger…
- 이러한 객체가 두개이상 있으면
- 프로그램이 이상하게 돌아갈 가능성.
- 자원을 불필요하게 사용.
- 결과에 일관성이 없어질 수 있음.
- 정적 클래스와 메소드의 접근 변경자(public, private...)를 잘 다룰 줄 알아야함
전역변수
- 싱글톤 패턴과 비슷.
- 단점
- 객체를 한번도 쓰지 않는다면 리소스 낭비
- 싱글톤 패턴은 필요할 때만 객체를 생성 가능.
고전적인 싱글톤 패턴
public class Singleton {
private static Singleton singleton; // Singleton 클래스의 하나뿐인 인스턴스를 저장하는 정적변수
private Singleton() {} // 생성자를 private로 선언했으므 Singleton 클래스에서만 생성자 생성 가능
public static Singleton getInstance() { // instance 호출
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
- singleton 은 클래스의 하나뿐인 정적변수
- 인스턴스가 필요한 상황 전까지 인스턴스를 만들지 않고 필요할 때 인스턴스를 생성. ⇒ Lazy instantiation
- 유일한 객체
- public으로 지정된 생성자가 없음.
- getInstance() 정적 메서드 존재. 정적 인스턴스 호출
싱글톤 패턴
💡 싱글턴 패턴
클래스 인스턴스를 하나만 만들고 그 인스턴스로의 전역 접근을 제공.
문제
- 멀티 스레딩에서의 문제가 생김.
- 두 스레드에서 다른 객체가 생김.
해결책
synchronized 키워드 사용
- synchronized 키워드만 추가하면 한 스레드가 메소드 사용을 끝나기 전까지 다른 스레드는 기다려야함.
- 속도 문제가 생길 수 있음
public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables here
private Singleton() {}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// other useful methods here
public String getDescription() {
return "I'm a thread safe Singleton!";
}
}
선언시 인스턴스 생성
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
- JVM에서 Singleton의 인스턴스를 하나 생성
voliate 키워드 사용
- DCL(Double-Checked Locking) 사용
- 인스턴스가 있는지 확인 후 동기화 블록에 들어감
- synchronized 내부의 블록에 한번 더 체크 하므로 동기화
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
고찰
- 클래스 로더마다 서로 다른 네임스페이스 정의하기 때문에 클래스 로더가 두개 이상이면 같은 클래스 여러번 로딩하기에 객체가 두개 이상 생길 수 있음.
- 리플랙션, 직렬화, 역직렬화에서 문제가 생길 수 있음. ⇒ 체크하면서 개발해야함.
- 싱글턴은 느슨한 결합 원칙에 위배됨.
- 클래스는 기본적으로 하나의 책임만 져야함. 하지만 싱글턴은
- 하나의 클래스가 자신의 인스턴스를 관리하는 일
- 인스턴스를 사용하는 목적.
- 이 두가지 책임을 가짐.
요약
'기타 > 디자인패턴' 카테고리의 다른 글
[Design Pattern] Adapter Pattern (0) | 2024.06.04 |
---|---|
[Design Pattern] Command Pattern (2) | 2024.06.03 |
[Design Pattern] Factory Pattern (0) | 2024.05.29 |
[Design Pattern] Decorator Pattern (0) | 2024.05.28 |
[Design Pattern] Observer Pattern (0) | 2024.05.27 |