[Kotlin] 싱글톤
Single-expression function
💡 람다식을 이용해서 메소드를 간결하게 정의할 수 있다
- 설명
- 자바 8과 동일하게 코틀린도 람다식을 지원한다.
- 하나의 메소드를 간결하게 표현할 수 있는 방법이다.
Kotlin의 람다식 구조
예시 코드
세 개의 숫자의 평균을 리턴해주는 함수를 람다식으로 정의한 것이다.
fun add(num1:Int, num2:Int, num3:Int) = (num1+num2+num3)/3
메소드를 선언하지 않고 로직을 저장할 수 있다.
var add = {num1: Int, num2: Int, num3: Int -> (num1+num2+num3) / 3} println("평균값은 ${add(10,20,30)}입니다")
싱글톤 이란?
💡 메모리 전역에서 유일한 객체임을 보장할 수 있다.
- 설명
- 보통 객체는 자원이 가능한 만큼 생성할 수 있다.
- 각각의 객체는 상이한 위치정보를 가지고 있어서 저장하는 값도 객체마다 고유하다.
- 싱글턴을 활용하면 해당 객체는 메모리 전역에서 유일함을 보장하고 위치정보가 고정이다.
- 프로그램이 실행되는 시점에 메모리에 바로 로드해서 위치를 잡는다.
- Kotlin의 싱글턴 구현방법
- 코틀린은 companion, object 키워드로 싱글턴을 구현할 수 있다.
어디에 사용하나?
설명
- 싱글턴 객체는 전역적으로 활용할 수 있어서 다른 클래스들에서 쉽게 접근할 수 있다.
- 전역에서 공통적으로 사용하는 정보라면 메모리를 더욱 효율적으로 활용할 수 있다.
- 객체 자원간의 충돌을 방지할 수 있다.
예시
- 프로그램에서 키보드 객체를 무한하게 제작한다면 입력순서가 꼬일 수 있다.
- 키보드 객체는 싱글턴으로 제작해서 사용하고 싶을때 객체을 얻어오는 방법으로 사용한다.
예시 코드
- 객체를 생성하지 않고도 클래스 정보에 접근할 수 있다. (생성자 호출X)
fun main() {
Bird.fly("참새")
}
object Bird {
fun fly(name:String) {
println("${name}가 날아요~")
}
}
- 객체를 생성하지 않고도 클래스 정보에 접근할 수 있다. (생성자 호출O)
fun main() {
// trash와 같이 생성자에 매개변수 전달 가능
var singletonObject1 = MySingletonClass.getInstance(trash = 1)
singletonObject1.setNum(5)
println("num값은: ${singletonObject1.getNum()}")
// singletonObject2에서 num을 10으로 대입
var singletonObject2 = MySingletonClass.getInstance(trash = 1)
singletonObject2.setNum(10)
// singletonObject1의 num이 10으로 출력됨
// singletonObject1과 singletonObject2는 같은 객체를 공유하기 때문
println("num값은: ${singletonObject1.getNum()}")
}
class MySingletonClass private constructor() {
private var num:Int = 0
companion object {
@Volatile private var instance: MySingletonClass? = null
private var trash = 0
fun getInstance(trash: Int): MySingletonClass {
this.trash = trash
// 외부에서 요청왔을때 instance가 null인지 검증
if(instance == null) {
// synchronized로 외부 쓰레드의 접근을 막음
// 쓰레드는 다음챕터에서 소개합니다!
// 쓰레드간의 객체상태 혼돈을 막기위해 사용한다고 이해해주세요
synchronized(this) {
instance = MySingletonClass()
}
}
return instance!!
// 엘비스연산자와 뒷장에서배울 scope function을 이용하면
// 아래와같이 더욱 직관적인 코드 작성이 가능합니다
// return instance ?: synchronized(this) {
// // also는 호출한 객체를 it으로 넘김
// // instance가 null이라면 새로 생성하고 아니면 무시함
// instance ?: MySigletonClass().also {
// instance = it
// }
// }
}
}
fun setNum(num: Int) {
this.num = num
}
fun getNum(): Int{
return this.num
}
}