Skip to content

Latest commit

ย 

History

History
322 lines (229 loc) ยท 8.36 KB

3_State_Swift.md

File metadata and controls

322 lines (229 loc) ยท 8.36 KB

1. State Pattern ์ด๋ž€?

State Pattern ์€ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๊ฐ์ฒด์˜ ๋™์ž‘๋„ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋™์ž‘ ๋””์ž์ธ ํŒจํ„ด์˜ ํ•œ ์ข…๋ฅ˜ ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์ž๋ฉด, ์ปดํ“จํ„ฐ๊ฐ€ ์ผœ์ ธ์žˆ๋Š” ์ƒํ™ฉ์—์„œ๋Š” ์ „์› ๋ฒ„ํŠผ์˜ ์—ญํ• ์€ off, ๊บผ์ ธ์žˆ๋Š” ์ƒํ™ฉ์—์„œ๋Š” on ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ปดํ“จํ„ฐ์˜ ์ƒํƒœ์˜ ๋”ฐ๋ผ ๋™์ž‘(๋ฉ”์„œ๋“œ)์ด ๋‹ฌ๋ผ์ง€๋Š” ๊ฒƒ์ด๋‹ค!


original

Context - ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๊ฐ–๊ณ  ์žˆ๊ณ  ๋™์ž‘์ด ๋ณ€๊ฒฝ๋˜๋Š” ๊ฐ์ฒด, Protocol ์˜ ๋‹คํ˜•์„ฑ ํŠน์ง•์„ ํ†ตํ•ด ๋™์ž‘์„ ๋ณ€๊ฒฝ
State - ๋ชจ๋“  ์ƒํƒœ์— ๋Œ€ํ•œ ๋™์ž‘, ํ•„์š”ํ•œ Method ์™€ Property ๋ฅผ ์ •์˜ ( Protocol )
Concrete State - State Protocol ์„ ์ฑ„ํƒ, Context ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€๋ฅผ ๊ตฌํ˜„


2. ์–ธ์ œ ์จ์•ผ ํ•˜๋‚˜์š”โ€ฆ?

  • ๋Ÿฐํƒ€์ž„ ์‹œ์ ์—์„œ ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด์„œ, ๋™์ž‘์ด ๋ฐ”๋€” ๋•Œ
  • ๊ฐ์ฒด์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ๋™์ž‘์— ๋Œ€ํ•œ ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ๋งŽ์•„์งˆ ๋•Œ

3. NetFlix ์š”๊ธˆ์ œ์— ๋”ฐ๋ฅธ State Pattern ์˜ˆ์‹œ

์ƒํƒœ์— ๋Œ€ํ•œ ๋™์ž‘

๊ตฌ๋…์ด ๋˜์–ด์žˆ๋Š”์ง€? โ†’ ์˜์ƒ ์žฌ์ƒ, ๋‹ค์šด๋กœ๋“œ ๋ถˆ๊ฐ€ Basic, Standard, Premium ์š”๊ธˆ์ œ ์ƒํƒœ โ†’ ์˜์ƒ ์žฌ์ƒ, ๋‹ค์šด๋กœ๋“œ ๊ฐ€๋Šฅ, ์š”๊ธˆ์ œ์— ๋”ฐ๋ฅธ ํ•ด์ƒ๋„ ์ฐจ๋“ฑ


class NetFlixApp {
    private var isSubscribed: Bool
    private var isBasic: Bool
    private var isStandard: Bool
    private var isPremium: Bool
    
    init(isSubscribed: Bool, isBasic: Bool, isStandard: Bool, isPremium: Bool) {
        self.isSubscribed = isSubscribed
        self.isBasic = isBasic
        self.isStandard = isStandard
        self.isPremium = isPremium
    }

    func changePremiumMembership() {
        self.isBasic = false
        self.isStandard = false
        self.isPremium = true
    }

    func playMovie() {
        if !isSubscribed {
            print("๊ตฌ๋… X, ์˜์ƒ ์žฌ์ƒ X")
        } else if isSubscribed && isBasic {
            print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 720P")
        } else if isSubscribed && isStandard {
            print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 1080P")
        } else if isSubscribed && isPremium {
            print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 1440P")
        }
    }

    func downMovie() {
        if !isSubscribed {
            print("๊ตฌ๋… X, ์˜์ƒ ๋‹ค์šด X")
        } else {
            print("๊ตฌ๋… O, ์˜์ƒ ๋‹ค์šด O")
        }
    }
}

let netflixApp = NetFlixApp(isSubscribed: true, isBasic: true, isStandard: false, isPremium: false)

netflixApp.playMovie()
netflixApp.downMovie()

netflixApp.changePremiumMembership()

netflixApp.playMovie()
netflixApp.downMovie()

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-04-19 แ„‹แ…ฉแ„’แ…ฎ 3 38 54

โš ๏ธ ๋ฌธ์ œ์ 

  • ๊ฐ์ฒด ์ง€ํ–ฅ์ ์ธ ๋ฐฉ์‹์ด ์•„๋‹ˆ๋‹ค
  • ์ƒํƒœ์— ๋”ฐ๋ฅธ ์กฐ๊ฑด ๋ถ„๊ธฐ๊ฐ€ ๋‚˜์—ด๋˜์–ด ์žˆ์–ด ์ง๊ด€์ ์œผ๋กœ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์›€
  • ์ƒํƒœ๋ฅผ ๋ฐ”๊พธ๋Š” ๋ถ€๋ถ„์ด ๋…ธ์ถœ๋˜์–ด ์žˆ์Œ
  • ์ƒˆ๋กœ์šด ์ƒํƒœ๊ฐ€ ์ƒ๊ธด๋‹ค๋ฉด ๋ชจ๋“  ๋ถ€๋ถ„์— ์žˆ์–ด์„œ ์ˆ˜์ •์ด ํ•„์š”

3-2. Enum ์œผ๋กœ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ

enum MembershipType {
    case unsubscribed
    case basic
    case standard
    case premium

    func play() {
        switch self {
        case .unsubscribed:
            print("๊ตฌ๋… X, ์˜์ƒ ์žฌ์ƒ X")
        case .basic:
            print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 720P")
        case .standard:
            print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 1080P")
        case .premium:
            print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 1440P")
        }
    }

    func download() {
        switch self {
        case .unsubscribed:
            print("๊ตฌ๋… X, ์˜์ƒ ๋‹ค์šด X")
        case .basic, .standard, .premium:
            print("๊ตฌ๋… O, ์˜์ƒ ๋‹ค์šด O")
        }
    }
}

class NetFlixApp {
    var membership: MembershipType

    init(membership: MembershipType) {
        self.membership = membership
    }

    func changeMembership() {
        self.membership = .premium
    }

    func playMovie() {
        membership.play()
    }

    func downMovie() {
        membership.download()
    }
}

let netflixApp = NetFlixApp(membership: .unsubscribed)

netflixApp.playMovie()
netflixApp.downMovie()

netflixApp.changeMembership()

netflixApp.playMovie()
netflixApp.downMovie()
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-04-19 แ„‹แ…ฉแ„’แ…ฎ 3 47 37

โš ๏ธ ๋ฌธ์ œ์ 

  • enum ์œผ๋กœ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์ข‹์•„๋ณด์ด์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ ํ•„์š”
  • ์ƒํƒœ๊ฐ€ ์ถ”๊ฐ€๋  ๊ฒฝ์šฐ, ๊ธฐ๋Šฅ ์ˆ˜์ •์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ์ˆ˜์ •์— ์šฉ์ดํ•˜์ง€ ์•Š๋‹ค
  • OCP ๊ฐœ๋ฐฉ ํ์‡„ ์›์น™์„ ์ค€์ˆ˜ํ•˜์ง€ ๋ชปํ•จ ( ํ™•์žฅ์—๋Š” ์—ด๋ ค์žˆ๊ณ  ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค )

3-3. State Pattern ์ ์šฉ

// State
protocol State {
    func play()
    func download()
}
// ConcreteState
class unSubscribeState: State {
    func play() {
        print("๊ตฌ๋… X, ์˜์ƒ ์žฌ์ƒ X")
    }
    
    func download() {
        print("๊ตฌ๋… X, ์˜์ƒ ๋‹ค์šด X")
    }
}

class BasicState: State {
    func play() {
        print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 720P")
    }
    
    func download() {
        print("๊ตฌ๋… O, ์˜์ƒ ๋‹ค์šด O, 720P")
    }
}

class StandardState: State {
    func play() {
        print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 1080P")
    }
    
    func download() {
        print("๊ตฌ๋… O, ์˜์ƒ ๋‹ค์šด O, 1080P")
    }
}

class PremiumState: State {
    func play() {
        print("๊ตฌ๋… O, ์˜์ƒ ์žฌ์ƒ O, 1440P")
    }
    
    func download() {
        print("๊ตฌ๋… O, ์˜์ƒ ๋‹ค์šด O, 1440P")
    }
}
// Context
class NetFlixApp {
    var membership: State
    
    init(membership: State) {
        self.membership = membership
    }
    
    func changeMembership() {
        self.membership = PremiumState()
    }
    
    func playMovie() {
        membership.play()
    }
    
    func downMovie() {
        membership.download()
    }
}

var myNetFlixApp = NetFlixApp(membership: unSubscribeState())

myNetFlixApp.playMovie()
myNetFlixApp.downMovie()

myNetFlixApp.changeMembership()

myNetFlixApp.playMovie()
myNetFlixApp.downMovie()
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-04-19 แ„‹แ…ฉแ„’แ…ฎ 3 47 37

4. ์ •๋ฆฌํ•ด๋ณด์ž๋ฉด~

๐Ÿ’ก ์žฅ์ 

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

โš ๏ธ ๋‹จ์ 

  • ๊ฐœ๋ณ„ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๊ด€๋ฆฌํ•ด์•ผํ•  ํด๋ž˜์Šค ์ฆ๊ฐ€
  • ๊ฐ์ฒด๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋Š” ์ƒํƒœ์˜ ์ˆ˜๊ฐ€ ์ ๋‹ค๋ฉด ํŒจํ„ด์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์Œ

4-2. ์ „๋žต ํŒจํ„ด๊ณผ ์ฐจ์ด์ 

  • ๋‘ ํŒจํ„ด ๋ชจ๋‘ ๋™์ž‘์„ ์บก์Šํ™”ํ•˜์ง€๋งŒ ์˜๋„๊ฐ€ ๋‹ค๋ฅด๋‹ค.
  • ์ „๋žต ํŒจํ„ด์€ ๋Ÿฐํƒ€์ž„์— ํŠน์ • ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ ํƒํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘๋Š” ๋ฐ˜๋ฉด, ์ƒํƒœ ํŒจํ„ด์€ ๊ฐ์ฒด์˜ ์ƒํƒœ ๊ฐ„ ์ „ํ™˜์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

4-3. State ๊ฐ€ ๋ณ€๊ฒฝ๋  ๊ฐ€๋Šฅ์„ฑ vs ๊ด€๋ จ ๋™์ž‘์ด ๋ณ€๊ฒฝ๋  ๊ฐ€๋Šฅ์„ฑ


๐Ÿ’ก ๋„ทํ”Œ๋ฆญ์Šค ๊ธฐ๋Šฅ ์ค‘ ๊ณต์œ ํ•˜๊ธฐ๊ฐ€ ์ƒ๊ฒผ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค!


  • ๊ณผ์—ฐ Enum ๋ฐฉ์‹์ด ๋‚˜์œ ๊ฒƒ์ธ๊ฐ€..? ๋ผ๋Š” ๊ณ ๋ฏผ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-04-19 แ„‹แ…ฉแ„’แ…ฎ 4 58 58

โš ๏ธ ๋ฌธ์ œ์ 

  • Concrete State ๊ฐ€ ๋งŽ๊ณ  State ์˜ ๋™์ž‘ ๋ฉ”์„œ๋“œ๊ฐ€ ์ ์„ ๊ฒฝ์šฐ ์ˆ˜์ •ํ•  Class ๊ฐ€ ๋งŽ์•„์ง„๋‹คโ€ฆ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-04-19 แ„‹แ…ฉแ„’แ…ฎ 4 59 49

โš ๏ธ ๋ฌธ์ œ์ 

  • ๋‹จ์ผ ์ฑ…์ž„ ์›์น™์„ ์ค€์ˆ˜ํ•  ์ˆœ ์—†๋‹คโ€ฆ.
  • ์ˆ˜์ •ํ•  ํŒŒ์ผ์ด ๋‚˜๋ˆ ์ ธ ์žˆ์ง€ ์•Š๊ณ  ์ˆ˜์ •ํ•  ๋ถ€๋ถ„์ด ์ ๋‹ค!