Kotlin/Kotlin 프로그래밍
[Kotlin] Kotlin의 싱글톤 패턴(Singleton Pattern)
주 녕
2022. 2. 5. 23:09
반응형
Kotlin으로 프로그래밍을 하다보니 싱글톤에 대한 개념이 정확하게 서있는 것 같지 않아서, 포스팅을 통해 정리해보려고 한다.
우선 Java의 static과의 차이, object와 companion object의 차이를 중심적으로 정리한다.
싱글톤 패턴 (Singleton Pattern)
- 어떤 클래스의 인스턴스는 오직 하나임을 보장하며, 이 인스턴스는 전역에서 접근할 수 있는 디자인 패턴이다.
- 어플리케이션의 시작부터 종료까지 1번의 생성으로 고정된 메모리 영역을 가지므로, 메모리를 효율적으로 사용할 수 있다. (in Android)
Kotlin의 object
The initialization of an object declaration is thread-safe and done on first access.
- object 선언 초기화는 thread-safe하며, 첫번째 접근 때 수행된다.
- Kotlin에서 싱글톤 선언을 쉽게 하기 위해 만든 키워드 → single-instance class 생성 keyword
- object 선언은 로컬일 수는 없지만(함수 내부에 직접 중첩X), 다른 object 선언이나 inner-class가 아닌 경우 nested 가능
object VS. companion object
object
object RetrofitServiceImpl {
private const val BASE_URL = ""
private val retrofit:Retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
companion object
class MySingleton private constructor() {
companion object {
private var instance: MySingleton? = null
private lateinit var context: Context
fun getInstance(_context: Context): MySingleton {
return instance ?: synchronized(this) {
instance ?: MySingleton().also {
context = _context,
instance = it
}
}
}
}
}
1. 선언 구조에서의 차이
- object는 클래스 외부에서 선언이 되지만,
- companion object는 클래스 내부에서 선언이 된다.
2. 사용 방법
- object
- object로 선언된 클래스는 별도의 객체 생성없이 바로 호출할 수 있다.
- object는 접근 시점에 하나의 객체만 생성되므로 생성자가 없는 클래스만 사용할 수 있다.
- object를 초기화하기 위해서는 init 블록을 사용하며 처음에만 실행됨
- object 내에 선언된 속성과 함수는 클래스명.(함수/필드)로 호출이 가능함
- companion object
- companion object로 생성한 파라미터가 있는 클래스는 객체를 생성할 수 있다.
- 상속 관계에서 companion 멤버는 가려진다.
- 여러 개의 객체(이름이 다른)를 생성할 수 있지만, 클래스의 메모리 주소값은 동일하다.
- companion object 내에 선언된 속성과 함수는 클래스명/객체명.(함수/필드)로 호출이 가능하다.
Java의 static, final
Java의 static
- 객체 생성 없이 사용할 수 있는 필드 → 정적 멤버
- 메모리에서 static 영역에 저장되어 프로그램이 종료될 때까지 남아있음
- → 객체 생성 필요 없음, GC(heap 영역)이 제대로 이뤄지지 않아 퍼포먼스 문제가 생길 수 있음
- 정적멤버는 클래스명.~ 으로 사용 가능
- 객체를 생성해서 접근하는 것은 지양
Java의 final
- 최종적인 == 수정이 불가능
- 변수 → 한번 초기화되면 수정이 불가능한 값
(static 키워드를 추가해 메모리에 1번만 생성하고, 모든 곳에서 공유할 수 있도록 한다 → final만 붙여서는 상수X) - 함수 → 오버라이딩 불가능
- 클래스 → 상속 불가능
- 변수 → 한번 초기화되면 수정이 불가능한 값
Java의 static final
- 객체 생성없이 접근이 가능하고, 수정이 불가능
Kotlin의 object, companion object 디컴파일
companion obejct 디컴파일
class Test1 {
companion object Junyoung {
val test = "junyoung"
fun printTest(): String {
return test
}
}
}
public final class Test1 {
@NotNull
public static final Junyoung Junyoung = new Junyoung((DefaultConstructorMarker)null);
public static final int $stable;
@NotNull
private static final String test = "junyoung";
...
public static final class Junyoung {
private Junyoung() {
}
@NotNull
public final String getTest() {
return Test1.test;
}
@NotNull
public final String printTest() {
return this.getTest();
}
...
}
}
- final class 내부에 static final class로 디컴파일됨
- 내부 함수들은 final로 선언되어 상속 불가능
- final class 내부에 static final 객체로 생성됨
object 디컴파일
object Test2 {
val test2 = "junyoung2"
fun printTest2(): String {
return test2
}
}
public final class Test2 {
@NotNull
public static final Test2 INSTANCE = new Test2();
@NotNull
private static final String test2 = "junyoung2";
public static final int $stable;
private Test2() {
}
@NotNull
public final String getTest2() {
return test2;
}
@NotNull
public final String printTest2() {
return test2;
}
}
- final class로 디컴파일됨
*내부에 static 변수나 함수를 생성하고 싶다면 @JvmStatic 어노테이션을 이용할 수 있다
reference >
- https://kotlinlang.org/docs/object-declarations.html#semantic-difference-between-object-expressions-and-declarations
- https://gobae.tistory.com/3
- https://hungseong.tistory.com/28
수정 이력 >
- 해당 글은 2024-09-15 일자로 수정되었습니다.
제 글에 오류가 있어 수정했고, 앞으로는 더 공부하고 신중히 글을 쓰겠습니다.
아직 많이 부족합니다... 앞으로도 잘못된 부분에 대한 지적해주시면 너무 감사하겠습니다 🙇♀️
이전에 제 글을 보셨던 분들께 혼란을 드린 점 죄송합니다...!
반응형