싱글톤 패턴
- 어떤 클래스의 인스턴스는 오직 1개임을 보장, 이 인스턴스는 전역에서 접근할 수 있는 디자인 패턴이다.
- 어플리케이션의 시작부터 종료까지 1번의 생성으로 고정된 영역 메모리를 가지므로, 메모리를 효율적으로 사용할 수 있다
싱글톤 패턴 사용 이유
- 프로그램에서 키보드 객체를 무한하게 제작한다면? → 입력순서가 꼬임
- 안 될건 없지만, 중복된 동작을 하는 객체를 그 때마다 생성시키면 메모리가 낭비됨
- 보통 객체는 자원이 가능한 만큼 생성할 수 있고, 각각의 객체는 상이한 위치정보/고유한 저장값을 지님
- 싱글턴을 활용하면 해당 객체는 메모리 전역에서 유일함을 보장하고 위치정보가 고정
- 프로그램이 실행되는 시점에 메모리에 바로 로드해서 위치를 잡음
- 객체 자원간의 충돌 방지, 전역적으로 활용하여 다른 클래스들에서 쉽게 접근, 효율적인 메모리 활용
장점
싱글톤 패턴으로 생성된 인스턴스는 오직 한개만 생성되니 고정된 메모리 영역을 사용하기 때문에 해당 인스턴스에 접근할 때
메모리 낭비를 방지할 수 있고 이미 생성된 인스턴스를 활용하니 속도 측면에서도 이점
가장 큰 장점은 앱의 다른 화면 또는 클래스간에 데이터 공유가 쉽다는 점, 싱글톤 인스턴스가 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있기 때문
단점
가장 중요한 것은 싱글톤 패턴은 하나만 생성되어야 하지만, 단일 스레드가 아닌 멀티 스레드에서 생성하는 경우, 실제로 클래스의 인스턴스가 1개만 생성된다는 것을 보장할 수 없다는 점이다.
개발을 하다보면 객체에 대한 하나의 인스턴스만 필요할 때, 하나의 인스턴스를 재사용하기 위해 싱글톤 패턴을 구현해야 할 일이 생긴다!!
다음 그럼 코틀린의 object 키워드를 사용하여 싱글톤 패턴을 적용시켜 보자
object 키워드를 이용한 싱글톤 패턴
코틀린에서는 이를 단 하나의 키워드로 구현한다. 바로 object 키워드이다. 싱글톤으로 구현되어야 하는 클래스를 object 키워드를 사용함으로써 싱글톤으로 구현할 수 있다.
object SingletonClass {
}
SingletonObject는 한 번만 생성되는 클래스의 인스턴스로 내부의 모든 값들 역시 한 번만 생성된다.
예를 들어 다음과 같이 SampleClass의 인스턴스를 object내에서 생성했다고 해보자.
object SingletonClass {
val sampleString = "Sample String"
}
여기서 sampleString는 한 번만 생성된다. 따라서 SingletonObject.sample 은 어디서나 같은 인스턴스가 된다.
object SingletonClass {
val sampleString = "Sample String"
}
fun main() {
if (SingletonObject.sampleString == SingletonObject.sampleString)
println("true")
if (SingletonObject.sampleString === SingletonObject.sampleString)
println("ture")
}
//출력 결과
//true
//true
object를 사용할 때의 문제점
object를 사용하면 해당 객체의 초기화가 object 객체에 처음 접근될 때 이루어진다. 그 말은 내부의 모든 변수들이 초기화 된다는 뜻이다.
예를 들어 아래 SingletonClass는 firstValue에 접근하면 SingletonClass가 초기화 되기 때문에 secondValue도 초기화된다.
object SingletonClass {
val firstValue = "first"
val secondValue = "second"
}
해결책:내부 변수들의 초기화 시점 조정
object 자체가 접근 시 메모리에 곧바로 올라가는 것은 막지 못하지만, 내부 변수들을 by lazy를 이용해 생성함으로써 호출될 때 초기화를 지연 될 수 있게 만들 수 있다.
아래와 같이 object 내부의 변수값을 by lazy를 통해 지연 생성(호출될 때 메모리 상에 올라가도록 하는 방법)을 하도록 만들면 된다.
object SingletonClass {
val firstValue = "first"
val lazyValue by lazy { "lazy" }
}
그렇게 한다면 lazyValue는 호출될 때 처음 메모리 상에 올라가도록 할 수 있다.
이 방법을 통해 SingletonClass 내부에 많은 변수가 있을 때 메모리를 많이 잡아먹는 변수들을 지연생성을 하도록 함으로써 메모리를 최적화할 수 있다.
출처: https://kotlinworld.com/166 [조세영의 Kotlin World:티스토리]
'안드로이드 프로그래밍 > design pattern' 카테고리의 다른 글
[kotlin] Strategy Pattern 이란 (0) | 2024.07.16 |
---|