Home 싱글톤 패턴(Singleton Pattern)
Post
Cancel

싱글톤 패턴(Singleton Pattern)


싱글톤 패턴이란?

  • 특정 클래스가 단 하나만의 인스턴스를 생성하여 사용하기 위한 패턴
  • 생성자를 여러 번 호출하더라고 하나의 인스턴스를 보장해준다.
  • Socket Connection, DB JDBC Connection, Spring Bean 등 사용

장단점

장점

  • 유일한 인스턴스: 인스턴스는 앱 전역에서 단 하나만을 보장해주기 때문에 일관된 상태 및, 접근이 용이하다.
  • 메모리 절약: 동일한 객체를 중복생성 해주지 않아도 되기때문에 메모리를 절약할 수 있다.
  • 지연 초기화: 인스턴스가 실제로 사용되는 시점에 생성하여 초기 비용을 줄일 수 있다.

단점

  • 결합도 증가: 싱글톤 패턴은 전역에서 접근을 허용하기 때문에 해당 인스턴스에 의존하는 경우 결합도가 증가할 수 있다.
  • 테스트 복잡성: 싱글톤 클래스를 의존하는 클래스는 결합도 증가로 인해 테스트가 어려울 수 있다.
  • 상태 관리의 어려움: 만약, 싱글톤 클래스가 상태를 가지고 있는 경우 전역에서 사용되어 변경될 수 있다. 이로 인해 예상치 못한 동작이 발생할 수 있다.

구현 예제

이른 초기화(Eager Initialization)

1
2
3
4
5
6
7
8
9
public class Singleton {
private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
  • 클래스 로더가 초기화하는 시점에 정적 바인딩을 통해 해당 인스턴스를 메모리에 등록하기 때문에 Thread-safe 하다.
  • 객체를 미리 생성 하기 때문에 해당 인스턴스를 사용하지 않으면 메모리 측면에서 손해



지연 초기화(Lazy Initialization)

1
2
3
4
5
6
7
8
9
public class Singleton {
    private Singleton(){}

    private static final Singleton singleton = new Singleton();
    
    public static Singleton getInstance() {
        return singleton;
    }
}
  • getInstance()를 최초로 실행할 때에만 객체를 생성 하기 때문에 메모리 효율이 좋다.
  • Trhead-safe 하지 않다.



지연 초기화, 동기화 처리(Lazy Initialization with synchronized)

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
    private static Singleton instance;
    private Singleton() { }
 
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  • 메모리를 효율적으로 사용하며, Tread-safe 하다
  • 매번 호출시 동기화때문에 성능이 떨어진다.



LazyHolder - 지연 초기화, Static Inner Class 사용

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
    private Singleton() { }
 
    private static class SingletonHolder {
        public static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singlton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  • getInstance()가 호출될 때 SingletonHolder 클래스가 호출이 되면서 실제 인스턴스가 만들어지기 때문에 성능 이슈가 없다.
  • 리플렉션을 이용하여 생성자를 생성하면 싱글톤을 깨뜨릴 수 있다.



열거 타입(enum) 사용

1
2
3
4
5
6
7
8
9
enum Singleton {
    INSTANCE; 

    private int value = 3;

    public int getValue() {
        return value;
    }
}
  • 절대적으로 싱글톤을 보장해준다.
  • enum 기본 특성 때문에 다른 클래스 상속이 불가능하다
  • 클래스 로드하는 순간 미리 생성한다.


마치며

  • 열거타입 or LazyHolder방법을 사용하자


참고

This post is written by PRO.