상태 패턴이란 무엇인가?
상태에 따라 다르게 동작해야 할 때 사용할 수 있는 패턴이다.
볼링으로 언제 사용할 수 있는지 알아보자.
볼링은 총 10 프레임이 있다. 혼자 친다고 가정하고, 현재 프레임의 상태를 예로 들어보자.
프레임의 상태란 한 프레임에서 스트라이크, 스페어, 미스, 1번의 투구만 한 상태, 아직 투구 하지 않은 상태
이렇게 총 5가지의 상태이다.
아직 투구를 하지 않은 상태에서 투구를 시도하면 → 1번의 투구만 한 상태 or 스트라이크 상태가 되어야 하고,
1번의 투구만 한 상태에서 투구를 시도하면 → 스페어 or 미스 상태가 되어야 한다.
이렇게 5가지의 상태에 따라 투구 기능은 다른 동작을 하게 되는 것이다.
클래스 레벨로 알아보자.
bowl 메서드만으로 예를 들어보자.
Throwing
→ 투구 위한 인터페이스
RunningState
→ 투구 하지 않은 상태, 1번의 투구만 한 상태의 추상 클래스
→ isEnd() : 진행 중인 상태이므로 false로 공통 처리
Ready
→ 아직 투구하지 않은 상태
FristBowl
→ 공을 1번만 굴린 상태
EndedState
→ 투구를 완료한 상태
→ isEnd() : 투구를 완료한 상태이므로 true로 공통 처리
Strike, Miss, Spare
이와 같이 5개의 상태에 따라 bowl() 기능에 대해 다른 기능을 필요로 할 때 상태 패턴을 적용할 수 있는 것이다.
뭐가 좋은거지?
- 상태가 변경되거나 추가 되어도 콘텍스트 클래스의 변경이 적어져 변경에 수월하다.
- 상태별로 완전 분리가 되어있어 각 상태의 수정이 수월하다.
그런데 모든 패턴이 비슷하다는 생각이 들었다. 결국 객체지향이란게 유연하게 코드를 변경하기 위함이라서 그런 것 같은데
장점은 항상 사용자 측으로갈 수록 변경이 필요없는 코드를 지향하게 된다.
상태를 변경하는 주체는 누가해야 할까?
결국 어쨌든 어디선가는 상태 값을 변경 해주는 코드가 있어야 한다. 그 것을 콘텍스트 클래스나 상태 클래스에서 해주어야 하는데
이는 상황에 맞게 정해야 한다.
상태의 개수가 적고, 변경이 적을 때
이 때는 컨텍스트 클래스에서 변경하는게 좋다고 생각한다.
아무래도 코드를 한눈에 보기 편하기 때문이다. 결국 추상화를 하면 할수록 코드는 분산되기 때문에 코드 파악이 힘든 점도 있다.
상태의 개수가 많고, 변경이 자주 일어날 때
이 때는 각 상태 클래스에서 변경을 하는 것이 좋다고 생각한다.
컨텍스트 클래스에서 하게 되면, 상태가 추가될 때 마다 컨텍스트 코드는 변경이 되어야 한다. 그럼 점점 코드가 꼬이게 될 것이기 때문이다.
이는 적절한 선택이 필요하지만 정말 어려운 것 같다. 나로서는 아직도 클래스 도출도 하기 어려운 단계이다.
지금은 남의 코드를 보고 이런 패턴이 적용 되었다고 설명을 들으면 이해할 수 있는 정도인 것 같다.
이 볼링 게임에서는 상태 클래스에서 변경하는 것을 택하였는데 상태도 좀 많다고 생각했고, 상태별 반환해야 하는 상태들이
여러 케이스가 있어서 택하게 되었다. 아직까지 내 경험상 대부분은 최대한 캡슐화는 하는 것이 변경에도 용이하지만 개발을 할 때도
편했어서 택한 점도 있다.
간단하게 적용한 코드를 보면 EndedState 클래스
는 더 이상 굴릴 수 없도록 하였고, FirstBowl과 Ready
는 각각 다른 동작을 해야하기 때문에
개별로 구현하였다.
'기타 IT' 카테고리의 다른 글
SSH란? (0) | 2022.03.22 |
---|---|
@ParameterizedTest를 언제 사용해야 할까? (0) | 2022.03.03 |
템플릿 메서드 패턴 (0) | 2021.12.29 |
전략(Strategy) 패턴 (0) | 2021.12.23 |
디미터 법칙과 Tell, Don't Ask 법칙 (3) | 2021.12.10 |