스테이트 패턴 정의
객체 내부에 구성되어있는 상태에 따라 객체의 행동을 바꾸는 패턴이다.
필요한 상황
스테이트 패턴
- 로봇의 상태에 따라 수행하는 동작을 바꾸고 싶을 때
- GUI 프로그램에서 상태에 따라 버튼의 Enable, Disable 등 여부를 바꾸고 싶을 때
- 상태 변수를 switch로 넣어서 case로 때려 넣은 코드가 있을 때 (리펙토링 대상!!)
Class 다이어그램
스테이트 패턴

코드
스테이트 패턴
public interface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
public class HasQuarterSate : State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine)
{
this.gumballMachine = gumballMachine;
}
public void insertQuarter()=> Console.WriteLine("손잡이를 돌렸습니다.");
public void ejectQuarter(){
Console.WriteLine("동전이 반환됩니다.");
gumballMachine.setState(gumballMachine.noQuarterState);
}
public void turnCrank() => Console.WriteLine("손잡이를 돌렸습니다.");
public void dispense()=> Console.WriteLine("알맹이가 나갈수 없습니다.");
}
public class SoldState : State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine)
{
this.gumballMachine = gumballMachine;
}
public void insertQuarter()=> Console.WriteLine("잠깐만 기다려 주세요. 알맹이가 나가고 있습니다.");
public void ejectQuarter()=> Console.WriteLine("이미 알맹이를 뽑으셨습니다.");
public void turnCrank(){}=> Console.WriteLine("손잡이는 한 번만 돌려주세요.");
public void dispense(){
gumballMachine.releaseBall();
if ( gumballMachine.count > 0){
gumballMachine.setState(gumballMachine.noQuarterState);
}
else{
Console.WriteLine("더이상 동전이 없습니다");
gumballMachine.setState(gumballMachine.soldOutState);
}
}
}
public class SoldOutState : State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine)
{
this.gumballMachine = gumballMachine;
}
//인터페이스 구현체..
}
public class NoQuarterState : State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine)
{
this.gumballMachine = gumballMachine;
}
//인터페이스 구현체..
}
인터페이스와 구현체
public class GumballMachine {
State soldOutState {get;set;}
State noQuarterState{get;set;}
State hasQuarterSate{get;set;}
State soldState{get;set;}
State state = soldOutState;
int count {get;set;};
public GumballMachine(int numberGumballs){
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterSate = new HasQuarterSate(this);
soldState = new SoldState(this);
this.count = numberGumballs;
if (numberGumballs > 0){
state = noQuarterState;
}
}
public void insertQuarter(){
state.insertQuarter();
}
public void ejectQuarter(){
state.ejectQuarter();
}
public void turnCrank(){
state.turnCrank();
state.dispense();
}
public void dispense(){
state.dispense();
}
public void setState(State state){
this.state = state;
}
public void releaseBall(){
Console.WriteLine("A gumball comes rolling out the solt.....");
if (count != 0){
count = count - 1;
}
}
}
상태패턴을 이용하는 Context Class
코드 설명
스테이트 패턴
1. 인터페이스와 구현체
public interface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
Context Class에서 제공하는 기능을 인터페이스 함수로 대체했다.
public class HasQuarterSate : State {
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine)
{
this.gumballMachine = gumballMachine;
}
public void insertQuarter()=> Console.WriteLine("손잡이를 돌렸습니다.");
public void ejectQuarter(){
Console.WriteLine("동전이 반환됩니다.");
gumballMachine.setState(gumballMachine.noQuarterState);
}
public void turnCrank() => Console.WriteLine("손잡이를 돌렸습니다.");
public void dispense()=> Console.WriteLine("알맹이가 나갈수 없습니다.");
}
인터페이스의 구현체는 Context Class 인스턴스를 가지고 있으며, 인터페이스 구현체를 직접 실행하면서 상태 변경이 필요한 경우 Context Class 인스턴스의 상태를 직접 변경한다. 이부분에서 Context Class와의 종속성이 생긴다. (결합성이 올라감..)
2. 스테이트패턴을 이용하는 Context Class
Context Class는 스테이트 구현체들을 모두 가지고 있으며, 기능 실행이 필요할 때 인터페이스 구현체들의 함수만 호출한다.
설명 보충을 위한 그림 자료
스테이트 패턴


필요에 따라 추가 설명
x
정리 및 결론
스테이트 패턴은 현재 프로그램의 상태에 따라 기능을 달리해야 할 때 적용할만한 패턴이다. 주요 특징은 아래와 같다.
1. 상태 인터페이스를 두고 그에 맞는 구현체들을 모든 상태 별로 구현한다.
2. 상태 인터페이스 구현체들은 온전히 자신의 기능만을 수행하며 상태 천이가 필요한 경우 Context Class의 상태 천이를 수행한다.
3. 전략 패턴과 유사하다.
개인적으로 상태 패턴을 실제로 사용한 사례를 보고싶다. 전략 패턴, 옵저버 패턴, 팩토리 패턴, 데코 패턴은 많이 쓰인다고 들었는데 상태 패턴을 사용하는 사례를 보지 못했다.
'Program > SW Design Patterns' 카테고리의 다른 글
| Mediator 패턴 (C++) (0) | 2024.07.31 |
|---|---|
| CH7 어댑터&퍼사드 패턴 (0) | 2023.03.19 |
| CH6 커맨드 패턴 (0) | 2023.03.07 |
| CH5 데코레이터 패턴 (1) | 2023.03.05 |
| CH4 팩토리 패턴 (0) | 2023.03.04 |