해당 포스팅은 한빛 미디어 헤드퍼스트 디자인 패턴(에릭 프리먼, 엘리자베스 롭슨 저)를 통해 공부한 내용을 정리한 블로그입니다.

아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁
좋은 프로그래머는 자기 두뇌를 사용한다. 그러나 좋은 가이드라인은 모든 케이스를 고려해야만 하는 노력을 줄여준다.
(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() 정적 메서드 존재. 정적 인스턴스 호출

싱글톤 패턴


💡 싱글턴 패턴
클래스 인스턴스를 하나만 만들고 그 인스턴스로의 전역 접근을 제공.

문제

MultiThread 동시성 문제

  • 멀티 스레딩에서의 문제가 생김.
    • 두 스레드에서 다른 객체가 생김.

해결책

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

+ Recent posts