본문 바로가기

안드로이드/디자인패턴

SingleTon

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