본문 바로가기

Study/Design Pattern

[Pattern] Singleton Pattern

Singleton Pattern

  • 어플리케이션이 시작될 때, 어떤 클래스가 최초 한 번만 메모리를 할당하고 해당 메모리에 인스턴스를 만들어 사용하는 패턴.
  • 즉, 인스턴스가 필요할 때, 똑같은 인스턴스를 만들지 않고 기존의 인스턴스를 활용하는 것.
  • 생성자가 여러번 호출되더라도 실제로 생성되는 객체는 하나이며 최초로 생성된 이후 호출된 생성자는 이미 생성한 객체를 반환한다.
  • java에서는 생성자를 private로 지정하여 다른곳에서 생성하지 못하도록 만들고, getInstance() 메서드를 통해 받아서 사용하도록 구현한다.

왜 쓸까요?

  • 객체를 생성할 때마다 메모리 영역을 할당받아 사용해야하는데 한번의 new를 통해 객체를 생성한다면 메모리 낭비를 방지할 수 있다.
  • 싱글톤으로 구현한 인스턴스는 전역 이므로 다른 클래스의 인스턴스들이 데이터를 공유할 수 있다는 장점이 있다.

언제 쓸까요?

  • 주로 공통된 객체를 여러개 생성해서 사용해야하는 상황에 쓴다.
  • ex) DB의 커넥션풀, 쓰레드풀, 캐시, 로그 기록 객체 ...
  • 인스턴스가 절대적으로 한개만 존재한다는 것을 보증하고 싶을 때 사용

단점

객체 지향 설계 원칙 중 open - close principle이란 것이 존재한다.

싱글톤 인스턴스가 혼자 너무 많은 일을 하거나, 많은 데이터를 공유시키면 다른 클래스들 간의 결합도가 높아지게 되면서 Open - Close Principle을 위배하게 된다.

결합도가 높아지게 되면 유지보수가 힘들고 테스트도 원활하게 진행할 수 없는 문제점이 발생한다.

따라서, 반드시 싱글톤이 필요한 상황이 아니면 지양하는 것이 좋다.


멀티 스레드 환경에서 안전한 싱글톤 만들기

Initialization on demand holder idiom (holder에 의한 초기화)

클래스 안에 클래스(holder)를 두어 JVM클래스 로더 매커니즘과 클래스가 로드되는 시점을 이용한 방법

이러한 방법을 실제로 가장 많이 사용한다.(일반적인 싱글톤 클래스 사용 방법)

public class Something {
    private Something() {
    }

    private static class LazyHolder {
        public static final Something INSTANCE = new Something();
    }

    public static Something getInstance() {
        return LazyHolder.INSTANCE;
    }
}
  • JVM의 클래스 초기화 과정에서 보장되는 원자적 특성을 이용해 싱글톤의 초기화 문제에 대한 책임을 JVM에게 떠넘기는걸 활용한다.
  • 클래스 안에 선언한 클래스인 holder에서 선언된 인스턴스는 static이다. 따라서 클래스 로딩 시점에서 한번만 호출된다.
  • final을 사용했기 때문에 다시 값이 할당되지 않는다.

'Study > Design Pattern' 카테고리의 다른 글

[Pattern] Factory Method Pattern  (0) 2022.01.15
[Pattern] Template Method Pattern  (0) 2022.01.15
[Pattern] Adapter Pattern  (0) 2022.01.15
[Pattern] 디자인 패턴 개요  (0) 2022.01.15
[WEB] MVC패턴  (0) 2021.10.14