본문 바로가기

Design/Design Pattern

[Design Pattern] State Pattern

이번 장에서는 상태(State) 패턴에 대해서 알아본다.
샘플 코드는 여기 (링크) 프로젝트의 테스트 코드로 정리해두었다.


상태 패턴이란?
위키백과에 다른 정의는 아래와 같다.

상태 패턴 인터페이스의 파생 클래스로서 각각의 상태를 구현함으로써, 또 패턴의 슈퍼클래스에 의해 정의되는
메소드를 호출하여 상태 변화를 구현함으로써 상태기계를 구현한다.

쉽게 풀어보면 어떠한 객체가 존재하고 객체의 상태가 존재할 때 상태를 관리하는 클래스들을 따로 분리하여
객체의 상태를 관리한다는 의미가 된다.

필자의 경우 아래의 이미지와 같이 버스의 혼잡 상태(이하 혼잡도, CrowdLevel)를 예로 알아보도록 하겠다.
버스의 혼잡도는 임의로 아래와 같이 변한다고 가정한다.
0 ~ 20명은 "여유"(CrowdLevel1), 21 ~ 30명은 "보통"(CrowdLevel2), 30명 초과는 "혼잡"(CrowdLevel3)으로 한다.


GoF Design Patterns에 따르면 아래와 같은 Class Diagram이 그려진다.

Context: 상태(State)를 가지고 있는 주체다.
State: Context의 상태 값을 변경시킬 구현체들의 인터페이스 또는 추상 클래스.
ConcreteStateA, ConcreteStateB: Context의 상태를 변경시킬 구현체.

위의 그림을 버스의 혼잡도에 적용시키면 아래와 같은 Class Diagram이 그려진다.

Bus: 혼잡도를 가지고 있는 주체다.
CrowdLevel: Bus의 혼잡도를 변경시킬 구현체들의 추상 클래스.
CrowdLevel1, CrowdLevel2, CrowdLevel3: 탑승자의 수에 따라 버스의 혼잡도를 변경시킬 구현체.


코드를 보면서 하나씩 살펴보도록 한다.

CrowdLevel Class
버스의 혼잡도를 변경시키는 getOnOffTheBus 메서드를 가지고 있다.

CrowdLevel1 Class
버스의 상태가 변경될 때마다 상태 객체를 생성하는 것을 방지하기 위하여 싱글톤 패턴을 적용하여 자기 자신을 생성하고 필요할 때 반환하도록 하였다.
getOnOffBus가 호출되면서 Bus 객체가 자기 자신을 같이 전달한다.
버스에 탑승한 승객이 CrowdLevel1의 범위인 0 ~ 20이라면 혼잡도 변화없이 탑승자의 수만 출력한다.
버스에 탑승한 승객이 CrowdLevel2의 범위인 21 ~ 30이라면 혼잡도를 CrowdLevel2로 변경시킨다.
버스에 탑승한 승객이 CrowdLevel3의 범위인 31 이상이라면 혼잡도를 CrowdLevel3으로 변경시킨다.

CrowdLevel2, CrowdLevel3 Class
CrowdLevel1과 유사한 방식으로 작동한다.

Bus Class
혼잡도 값인 CrowdLevel과 탑승한 승객 수를 가지고 있다.
승객이 탑승하거나 하차하는 경우 호출하는 getOnTheBus, getOffTheBus 메서드를 가지고 있다.
이 메서드가 호출되는 겨우 자신의 상태 값에게 새로운 상태 값 변화를 요청하기 위해 자신을 넘긴다.

BusStation Class
버스를 생성하고 임의로 승객을 승하차 시키기 위한 클래스.
총 10번의 고객 승하차가 이루어진다. 코드 상으로 보았을 때
1번째는 9명이 승차하고 5명이 하차하므로 결론적으로 4명이 승차하게 된다.
2번째는 20명이 승차하고 2명이 하차하므로 결론적으로 18명이 승차하게 된다.

코드를 실행시킨 결과는 아래와 같다.


지금까지 버스와 승객 수에 따른 혼잡도를 예시로 상태 패턴에 대해서 알아보았다.

'Design > Design Pattern' 카테고리의 다른 글

[Design Pattern] Flyweight Pattern  (0) 2022.02.04
[Design Pattern] Memento Pattern  (0) 2022.02.03
[Design Pattern] Mediator Pattern  (0) 2022.02.02
[Design Pattern] Observer Pattern  (0) 2022.02.02
[Design Pattern] Facade Pattern  (0) 2022.02.02