State Pattern
OOP에서는 프로그램 대상을 클래스로 표현함
state는 '상태 = 사물의 모양이나 형편'을 의미
상태를 클래스로 표현하면 클래스를 교체해서 '상태의 변화'를 표현할 수 있음
Strategy Pattern과 조금 유사함
__ init __
property로 state (기본 state는 'green')
setState
현재 state를 설정할 수 있는 함수
Speak
State에 따라서 녹색이면 green light
빨강이면 red light 출력
Wait
Wait 함수를 호출하면 state가 변함
하지만 state가 많아진다면 현재 코드 구조로는 복잡성을 대응하기 어려움
-> 이때 state pattern 사용가능
TrafficLight class
__ init __
기본 state로 GreenLight 가짐
setState
argument로 받은 state 변경
Speak
현재 상태 object의 speak 함수인 status() 호출
초록 불이라면 greenLlight class의 status() 호출
빨강 불이라면 redLight class의 status() 호출
Wait
speak와 마찬가지로 현재 상태 object의 wait 함수인 changeLight() 호출
status
현재 상태 출력
changeLight
argument로 받은 state로 변경
GreenLight, RedLight
State class를 상속받음
status
자신의 상태 출력
changeLight
상태 변경해주는 함수
TrafficLight 의 setState를 통해서 상태 변경해야됨
TrafficLight의 setState를 호출하기 위해서는 argument로 TrafficLight을 받아야함
개념 확장
State의 전환은 누가 관리해야 하는가?
상태를 클래스로 표현해서 ConcreteState 역할에 분담하는 것은 좋은 방법임
그러나 State 패턴을 사용할 경우 상태 전환은 누가 관리해야하는 지 생각해봐야함
Context 역할은 Traffic Light가 상태전환을 실제로 수행하도록 setState를 구현하였음
그러나 setState를 실제로 호출하는 것은 ConcreteState 역할의 GreenLight또는 RedLight 클래스임
즉, 상태전환을 상태에 의존한 동작으로 간주되고 있는데 이것은 장단점이 있음
장점 : 다른 상태로 전환하는 것에 대한 정보가 하나의 클래스 내에 정리되어 있고,
가령 GreenLight 클래스가 어떤 상태로 전환하는 지는 GreenLight 클래스의 코드만 읽으면 됨
단점 : 하나의 ConcreteState 역할이 다른 ConcreteState 역할을 서로 알아야한다는 것임
이것은 만약 하나를 삭제하고 싶으면 의존된 또 다른 것도 수정해야한다는 것을 의미함
-> 상태전환을 Concrete 에게 맡기면 클래스 사이의 의존관계가 깊어짐
Context역할에게 상태전환의 업무를 맡기면 되지 않는가?
- 그렇게 되면 각각의 ConcreteState 역할의 독립성이 높아지는 것은 좋음
- 그러나 이번에는 Context역할이 모든 ConcreteState 역할을 알아야하는 문제가 발생함.