본문 바로가기
Kotlin/Kotlin 프로그래밍

[Kotlin] Kotlin의 싱글톤 패턴(Singleton Pattern)

by 주 녕 2022. 2. 5.
반응형

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 >


수정 이력 >

  • 해당 글은 2024-09-15 일자로 수정되었습니다.
    제 글에 오류가 있어 수정했고, 앞으로는 더 공부하고 신중히 글을 쓰겠습니다.
    아직 많이 부족합니다... 앞으로도 잘못된 부분에 대한 지적해주시면 너무 감사하겠습니다 🙇‍♀️
    이전에 제 글을 보셨던 분들께 혼란을 드린 점 죄송합니다...!

 

반응형

댓글