[Kotlin ๊ธฐ์ดˆ] ์‹ฑ๊ธ€ํ†ค(Singleton) ํŒจํ„ด ์ดํ•ดํ•˜๊ธฐ
๋ฐ˜์‘ํ˜•

 

 

 

์ถœ์ฒ˜ velog.io/@haero_kim

 

 

์‹ฑ๊ธ€ํ†ค ๊ฐœ๋…

  • ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ๊นŒ์ง€ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด
  • ํ”„๋กœ๊ทธ๋žจ ์ „์—ญ์—์„œ, ์ด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณต์œ ํ•˜๋ฉฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ํ•˜๋Š” ๊ฒƒ
  • ์ฝ”ํ‹€๋ฆฐ์€ companionobject ํ‚ค์›Œ๋“œ๋กœ ์‹ฑ๊ธ€ํ„ด์„ ๊ตฌํ˜„

 

 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ์‚ฌ์šฉ ์ด์œ 

  • ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ‚ค๋ณด๋“œ ๊ฐ์ฒด๋ฅผ ๋ฌดํ•œํ•˜๊ฒŒ ์ œ์ž‘ํ•œ๋‹ค๋ฉด? → ์ž…๋ ฅ์ˆœ์„œ๊ฐ€ ๊ผฌ์ž„
  • ์•ˆ ๋ ๊ฑด ์—†์ง€๋งŒ, ์ค‘๋ณต๋œ ๋™์ž‘์„ ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ทธ ๋•Œ๋งˆ๋‹ค ์ƒ์„ฑ์‹œํ‚ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‚ญ๋น„๋จ
  • ๋ณดํ†ต ๊ฐ์ฒด๋Š” ์ž์›์ด ๊ฐ€๋Šฅํ•œ ๋งŒํผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ๊ฐ์˜ ๊ฐ์ฒด๋Š” ์ƒ์ดํ•œ ์œ„์น˜์ •๋ณด/๊ณ ์œ ํ•œ ์ €์žฅ๊ฐ’์„ ์ง€๋‹˜
  • ์‹ฑ๊ธ€ํ„ด์„ ํ™œ์šฉํ•˜๋ฉด ํ•ด๋‹น ๊ฐ์ฒด๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ „์—ญ์—์„œ ์œ ์ผํ•จ์„ ๋ณด์žฅํ•˜๊ณ  ์œ„์น˜์ •๋ณด๊ฐ€ ๊ณ ์ •
  • ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋˜๋Š” ์‹œ์ ์— ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ”๋กœ ๋กœ๋“œํ•ด์„œ ์œ„์น˜๋ฅผ ์žก์Œ
  • ๊ฐ์ฒด ์ž์›๊ฐ„์˜ ์ถฉ๋Œ ๋ฐฉ์ง€, ์ „์—ญ์ ์œผ๋กœ ํ™œ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋“ค์—์„œ ์‰ฝ๊ฒŒ ์ ‘๊ทผ, ํšจ์œจ์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ํ™œ์šฉ
  •  

 

 

์‹ฑ๊ธ€ํ†ค ์˜ˆ์‹œ

 

// ์ƒ์„ฑ์ž ํ˜ธ์ถœ 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
    }
}

 

 

์ฝ”ํ‹€๋ฆฐ์—์„œ์˜ ์‹ฑ๊ธ€ํ†ค

object SingletonObj {

}
  • ์ฝ”ํ‹€๋ฆฐ์—์„  object(์ž๋ฐ”์—์„œ์˜ static) ๋กœ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ฒŒ ๋˜๋ฉด, ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ๋™์‹œ์— ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉฐ
  • ์ด ๋•Œ, ๋ฌด์กฐ๊ฑด ๋‹จ์ผ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์„ ๋ณด์žฅํ•จ
  • ์ด ํด๋ž˜์Šค ์•ˆ์— ํ•„์š”ํ•œ ๊ฐ์ฒด, ๋ฉ”์†Œ๋“œ ๋“ฑ์„ ์ •์˜ํ•ด๋‘๋ฉด ํ”„๋กœ๊ทธ๋žจ ์ „์—ญ์—์„œ ์ด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Œ
  • ๋‹ค์–‘ํ•œ ์ œ์•ฝ ์กฐ๊ฑด(๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋”ฉ ํ™˜๊ฒฝ ๋“ฑ) ์„ ๊ณ ๋ คํ•  ํ•„์š” ์—†์ด, Thread-safe ํ•˜๊ณ  Lazyํ•œ ์ดˆ๊ธฐํ™”๋ฅผ ์–ธ์–ด ์ฐจ์›์—์„œ ์ง€์›

 

 


 

๋ฐ˜์‘ํ˜•
 ๐Ÿ’ฌ C O M M E N T