개념
객체의 인스턴스가 오직 1개임을 보장하고, 이 인스턴스에 접근할 수 있는 전역적인 접촉점을 제공하는 패턴
특징
- 생성 패턴(Creational Pattern) 중 하나이다.
- 생성된 인스턴스에 어디에서나 접근할 수 있다.
생성 패턴
- 시스템이 어떤 구체 클래스를 사용하는지에 대한 정보를 캡슐화한다.
- 인스턴스를 어떻게 만들고 어떻게 결합하는지에 대한 부분을 완전히 가려준다.
예시
- 로깅, 쓰레드 풀, 윈도우 관리자 등 여러 객체를 관리하는 역할의 객체
사용 이유
- 효율성이 좋다.
- 메모리 낭비 방지
- 최초 한 번의 new 연산자를 통해 고정된 메모리 영역을 사용한다.
- 속도 측면
- 클래스간 데이터 공유가 쉽다.
- 도메인 관점에서 인스턴스가 한 개만 존재하는 것을 보증하고 싶은 경우
- 직접 싱글톤을 구현하지 않고 프레임워크에게 싱글톤을 위임한다면 아래의 단점들을 해결받을 수 있다.
단점
- private 생성자로 인해 상속이 불가능하다.
- 상속을 통해서 다형성을 적용하기 위해서는 기본 생성자가 필요하다.
- 객체지향적이지 못한 static 필드와 static 메서드를 사용해야 한다.
- 테스트의 어려움
- 생성 방식이 제한적이기 때문에 mock 객체로 대체하기 어렵고, 동적으로 객체를 주입하기도 어렵다.
- 서버 환경에서 싱글톤이 1개만 생성됨을 보장할 순 없다.
- 클래스 로더를 어떻게 구성하느냐에 따라 1개 이상의 객체가 만들어질 수도 있다.
- 여러 JVM에 분산돼서 설치하면 독립적으로 객체가 생성된다.
- 전역 상태는 OOP에서 권장되지 않는다.
구현방법
Java Singelton
private inner static class
를 두어 싱글톤 인스턴스를 final
로 선언하는 방법
- 클래스 자신이 유일한 인스턴스로 접근하는 방법을 자체적으로 관리한다.
- 생성자를 private하게 만들어서 외부에서 인스턴스를 생성하지 못하게 차단한다.
- 클래스 내부에서 단 하나의 인스턴스를
private static
멤버 변수로 생성한다.
public static
메서드를 통해서 외부에 접근 방법을 제공한다.
public class Singleton {
private Singleton() {}
private static class SingletonHelper {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
}
static class
- JVM의 클래스 초기화 과정에서 원자성을 보장하는 원리를 이용한다.
SingletonHelper
클래스는 Singleton
클래스가 로드될 때 같이 로드되지 않고, getInstance()
가 호출될 때 인스턴스를 생성하고 JVM 메모리에 로드된다.
final
- 다시 instance가 할당되는 것을 막는다.
- thread-safe하게 구현 가능
synchronized
를 사용하지 않아 성능 저하 문제가 해결된다.
Spring Singleton
@Component
public class Singleton {
}
- 자바 언어 레벨에서 직접 구현하기 위한 내용들이 모두 제거됐다.
- 불필요한 코드들을 제거해서 객체를 재사용하고 객체지향스러운 개발을 할 수 있도록 도와준다.
- static 메서드나 private 생성자 등을 사용하지 않는다.
- 단점을 모두 극복
Singleton Registry
: 직접 싱글톤 형태의 객체를 만들고 관리하는 기능
출처