개념
싱글톤 패턴이란 클래스의 인스턴스가 하나만 있도록 하면서 이 인스턴스에 대해 Global Access Point를 제공하는 디자인 패턴이다.
- 싱글톤 패턴은 인스턴스를 하나만 생성하기 때문에 인스턴스를 여러개 생성하는 것보다 메모리 사용에서 이점이 있다.
- 생성 방식에 따라, 사용하지 않는데 인스턴스를 만들 수도 있기 때문에 메모리 낭비가 발생할 수도 있다.
- 다른 클래스 간의 데이터 공유가 쉽지만, 동시성 문제가 발생할 수 있다.
- 싱글톤의 구현 방법은 아래와 같이 여러가지가 존재한다.
- Eager Initialization
- Lazy Initialization
- Thread Safe Lazy Initialization
- Double-Checked locking
- Initialization on demand holder idiom
코틀린에서는 object
키워드를 사용하면 싱글톤 클래스를 만들 수 있다.
예시

1. Eager Initialization
class Singleton private constructor() {
companion object {
private var INSTANCE: Singleton = Singleton()
fun getInstance(): Singleton {
return INSTANCE
}
}
}
2. Lazy Initialization
class Singleton private constructor() {
companion object {
private var INSTANCE: Singleton? = null
fun getInstance(): Singleton {
return INSTANCE ?: Singleton().apply {
INSTANCE = this
}
}
}
}
3. Thread Safe Lazy Initialization
Kotlin의 object
로 선언하면 thread-safe하다.
class Singleton private constructor() {
companion object {
private var INSTANCE: Singleton? = null
@Synchronized
fun getInstance(): Singleton {
return INSTANCE ?: Singleton().apply {
INSTANCE = this
}
}
}
}
4. Double-check locking
class Singleton private constructor() {
companion object {
@Volatile private var INSTANCE: Singleton? = null
fun getInstance() = INSTANCE ?: synchronized(this) {
INSTANCE ?: Singleton().apply { INSTANCE = this }
}
}
}
- 인스턴스 생성 작업만 synchronized로 블럭킹 하는 방법이다.
- 메소드에 synchronized를 하게되면 호출이 많을 수록 성능이 떨어진다.
5. Initialization on demand holder idiom
자바 코드
public class Something {
private Something() {}
private static class LazyHolder {
static final Something INSTANCE = new Something();
}
public static Something getInstance() {
return LazyHolder.INSTANCE;
}
}
- JVM에서 Static Inner Class는 실행되는 시점에 초기화된다.
- 또한 클래스 초기화는 순차적으로 일어나는 것을 보장하기 때문에 동시성 문제가 발생하지 않는다.
코틀린으로 한다면 이런 느낌일 거 같다.
class Singleton private constructor() {
companion object {
class LazyHolder private constructor() {
companion object {
var INSTANCE = Singleton()
}
}
fun getInstance() = LazyHolder.INSTANCE
}
}
장단점
장점
- 클래스의 인스턴스를 하나만 가진다.
- Global Access Point를 얻는다.
- 필요한 시점(처음 호출되는)에 초기화 한다.
단점
- SRP(단일 책임 원칙)위반
- 클래스에 인스턴스가 하나만 있도록 함
- 해당 인스턴스에 대한 Global Access Point 제공
- 위 두가지 책임을 동시에 가지고 있다.
- 다중 스레드 환경에서 동시성 문제가 발생할 수 있다.
- 여러 쓰레드가 동시에 싱글톤 객체를 생성하여 인스턴스가 여러 개 생길 수도 있다.
- 유닛 테스트가 어렵다.
- Mock 객체를 만들 때 상속을 이용하는데 싱글턴은 상속을 할 수 없기 때문
Uploaded by N2T
'Programming > 디자인패턴' 카테고리의 다른 글
[Kotlin] Command Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.17 |
---|---|
[Kotlin] Factory Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.06 |
[Kotlin] Decorator Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.06 |
[Kotlin] Observer Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.05 |
[Kotlin] Strategy Pattern 예시코드 - 코틀린으로 쓴 디자인 패턴 (0) | 2023.04.05 |