본문 바로가기
Object-Oriented Programming/Design Pattern

State Pattern, 상태패턴

by yongmin.Lee 2022. 8. 2.

State Pattern

  • 객체 내부의 상태 변화에 따라 객체의 행위를 바뀔수 있게해주는 패턴
  • Context는 State 인터페이스를 참조
  • 상태가 많아지더라도 클래스의 개수는 증가하지만 코드의 복잡도는 증가하지 않기 때문에 유지 보수에 유리
  • 상태에 따른 동작을 구현한 코드가 각 상태 별로 구분되기 때문에 상태 별 동작 수정이 용이
  • 상태 변경의 주체가 Context인 경우
    •  State 객체들은 상태를 변경할 책임이 없어져서 코드가 간결해진다
    •  상태 개수가 많고 상태 변경 규칙이 자주 바뀐다면 Context의 상태 변경 코드가 복잡
  • 상태 변경의 주체가 ConcreateState인 경우
    • 새로운 상태가 추가되더라도 Context 코드가 받는 영향은 최소
    • 각 상태가 자신의 다음 상태를 알아야 한다

 

State Pattern 예시

1. state pattern 적용 전

class TicketMachine {
    private let NO_COIN = 0
    private let COIN_INSERTED = 1
    private var currentState 
    
    init() {
        self.currentState = NO_COIN
    }
    
    func insertCoin() {
        if currentState == NO_COIN {
            print("coin inserted!")
            currentState = COIN_INSERTED
        } 
        else if currentState == COIN_INSERTED {
            print("coin already inserted")
        }

    }
    
    func tapTicketButton() {
        if currentState == NO_COIN {
            print("print ticket error : no coin!")
        } 
        else if currentState == COIN_INSERTED {
            print("ticket is printed")
            currentState = NO_COIN
        }
    }
}
  • context : TicketMachine 클래스

 

2. state pattern 적용 후 

protocol CoinState {
	func insertCoin() -> CoinState
    func printTicket() -> CoinState
}

class NoCoinState: CoinState {
    func inseretCoin() -> CoinState {
        print("coin inserted")
        return CoinInsertdState()
    }
    
    func printTicket() -> CoinState {
        print("print ticket error : no coin")
        return NoCoinState()
    }
}

class CoinInsertdState: CoinState {
    func inseretCoin() -> CoinState {
        print("coin already inserted")
        return CoinInsertdState()
    }
    
    func printTicket() -> CoinState {
        print("ticket is printed")
        return NoCoinState()
    }
}
class TicketMachine {
    var currentState : CoinState
    
    init() {
        currentState = NoCoinState()
    }
    
    func inseretCoin() {
        let newState = currentState.inseretCoin()
        currentState = newState
    }
    
    func tapTicketButton() {
        let newState = currentState.printTicket()
        currentState = newState
    }
}

 

 

 

 

 

 

 

 

 

참고

https://johngrib.github.io/wiki/pattern/state/

https://en.wikipedia.org/wiki/State_pattern

https://steady-coding.tistory.com/387