object MySingleton { init { // 초기화 코드 } fun doSomething() { // 싱글톤 객체에서 수행할 작업 } }
- 싱글톤 오브젝트를 선언해둔다.
MySingleton.doSomething()
- 인스턴스를 생성해서 뭔가를 수행할 때에는 이렇게 작성한다.
클래스 내부에 선언되는 정적 멤버를 관리하는 데 사용
클래스 인스턴스 없이 해당 클래스의 인스턴스 멤버에 접근하거나 호출할 수 있도록 한다.
멤버를 클래스 이름을 통해 직접 호출할 수 있다.
class MyClass { companion object { fun myFunction() { println("Companion object의 함수입니다.") } } }
var my = myFunction()
으로 호출할 수 있다.Companion Object 내부에 프로퍼티와 생성자를 정의할 수 있다.
class MyClass { companion object { val myProperty: Int = 10 private var count: Int = 0 init { printlnln("Companion Object의 초기화 블록") } fun incrementCount() { count++ } fun getCount(): Int { return count } fun createInstance(value: String): MyClass { return MyClass(value) } } private constructor(value: String) { println("인스턴스 생성: $value") } } fun main() { println("프로퍼티 값: ${MyClass.myProperty}") //10 출력 MyClass.incrementCount() //count = 1 println("카운트 값: ${MyClass.getCount()}") //11 출력 val instance = MyClass.createInstance("Hello") //인스턴스 생성: Hello 출력 }
자 그럼, 다시 Companion Object로 싱글톤을 구현하는 부분을 이해해보자.
class MySingleton private constructor() { init { println("싱글톤 인스턴스 생성") } companion object { @Volatile private var instance: MySingleton? = null fun getInstance(): MySingleton { return instance ?: synchronized(this) { instance ?: MySingleton().also { instance = it } } } } fun doSomgthing() { println("싱글톤이 뭔가를 한다") } } fun main() { val singleton1 = MySingleton.getInstance() //싱글톤 인스턴스 생성 출력 val singleton2 = MySingleton.getInstace() //아무것도 출력되지 않음 println(sigleton1 == singleton2) //true 출력 singleton1.doSomething() //싱글톤이 뭔가를 한다 출력 }
여기서 synchronized를 사용한 것은 다중 스레드 환경에서의 안정성을 보장하기 위한 것이며, lazy를 쓰는 방법도 있다.
class MySingleton private constructor() { init { println("Singleton instance created") } companion object { val instance: MySingleton by lazy { MySingleton() } } fun doSomething() { println("Singleton is doing something") } } fun main() { val singleton1 = MySingleton.instance val singleton2 = MySingleton.instance println(singleton1 === singleton2) // true singleton1.doSomething() }
sychronized, lazy 부분 없이 object만 쓰거나 companion object만 사용해도 싱글톤을 구현할 수 있다.
class MySingleton private constructor() { init { println("Singleton instance created") } companion object { val instance = MySingleton() } fun doSomething() { println("Singleton is doing something") } } fun main() { MySingleton.instance.doSomething() }
[TIL-240404]