Singleton Pattern
오직 하나의 인스턴스만 제공하는 클래스
Why?
하나의 클래스를 여러 곳에서 사용하다보면 불필요하게 여러 개의 동일한 클래스가 생성되어 메모리 낭비가 일어날 수 있다.
또는 setting과 같이 인스턴스가 하나여야만 하는 클래스가 있을 수 있다.
따라서 어디서 사용되어도 동일한 기능을 제공하는 클래스라면 불필요하게 여러 개의 인스턴스를 생성할 필요 없이 하나의 인스턴스만 제공하면 효율적으로 메모리를 사용할 수 있게 된다.
class Test{
companion object {
private var instance: Test? = null
fun getInstance(): Test{
return instance ?: Singleton().apply {
instance = this
}
}
}
}
멀티스레드 환경에서의 문제점
멀티스레드 환경에서 클래스에 동시에 접근한다면 각 스레드는 서로 다른 인스턴스를 갖게 될 수도 있다.
해결 방법
1. 이른 초기화 (Eager Initialization)
class Test{
companion object {
private const val INSTANCE: Test = Test()
fun getInstance(): Test = INSTANCE
}
}
객체 생성 비용이 적다면 인스턴스를 미리 생성하여 서로 다른 인스턴스가 생성되는 것을 막을 수 있다.
2. Synchronized
class Test {
companion object{
private var instance: Test? = null
@Synchronized
fun getInstance(): Test{
if(instance == null) instance = Test()
return instance!!
}
}
}
synchronized 를 통해 동기화하여 동시 접근을 방지할 수 있다.
해당 작업은 동시성 기법 중 모니터 기법을 사용한다.
단점은 접근마다 체크하기 때문에 성능이 떨어질 수 있다.
3. Double Checked Locking
class Test{
companion object {
@Volatile private var instance: Test? = null
fun getInstance(): Test{
return instance ?: synchronized(this) {
instance ?: Test().apply {
instance = this
}
}
}
}
}
Instance가 null인 경우에만 synchronized를 사용하는 방법으로 기존의 메서드에서 Synchronized를 사용했을 때보다 성능을 향상시킬 수 있다.
4. Static Inner Class(권장)
class Test {
private object TestHolder{
val INSTANCE = Test()
}
companion object{
fun getInstance(): Test{
return TestHolder.INSTANCE
}
}
}
class: Test
inner class: TestHolder
inner class의 경우 class가 처음 생성될 때 초기화가 일어나기 때문에 지연 초기화의 장점을 가지면서 synchronized 보다 나은 성능을 갖는다.
Kotlin에서의 싱글톤 객체를 만들어주는 Object 키워드 또한 위와 같은 방법으로 동기화 문제를 해결하고 있다.
object ObjectClass
'안드로이드 > 디자인패턴' 카테고리의 다른 글
Data Layer (0) | 2025.03.09 |
---|---|
SOILD 원칙 (0) | 2025.03.08 |
함수형 프로그래밍 (0) | 2024.08.13 |
[Java] 객체 지향 (0) | 2024.01.24 |
[디자인 패턴] MVVM (0) | 2023.11.03 |