State Pattern (스테이트 패턴)

State Pattern

 


정의


Object의 내부 상태가 바뀜에 따라서 object의 행동을 바꿀 수 있다.


마치 object class가 바뀌는 것과 같은 결과를 얻을 수 있다.


State patternstateclass로 표현한다


그 이유는, class의 교체를 통해서 state의 변화를 나타낼 수 있고, 새로운 state를 추가해야 할 때, 편리하기 때문이다.

 


적용 영역


1.    Object의 행위가 object state에 의존하고 그 object의 행위가 실행 시점에서 object state에 따라 변화해야 할 경우


2.    Operation이 크고, objectstate에 따라 다수의 조건문을 포함하는 경우


 

State vs Strategy (pattern)


State pattern을 사용할 때는 state object의 행동이 캡슐화 된다


State에 따라 context object에서 여러 state object 중 한 object에게 모든 행동을 위임한다.


해당 object의 내부 state에 따라 현재 state를 나타내는 object가 바뀌고


그 결과 context object의 행동도 바뀐다. Clientstate object에 대해서 몰라도 된다.


하지만, strategy patternclient에서 context object한테 어떤 object를 사용할지 정한다


Strategy pattern은 주로 실행시에 전략 object를 변경할 수 있는 유연성을 제공하기 위한 용도로 쓰이며, 가장 적합한 전략 object를 선택해서 사용한다.


, strategy pattern은 외부에서 상황에 맞게 변화를 줄 수 있고, state pattern은 자신이 직접 상태변화에 관여한다는 것이다



구성요소


1.    State를 나타내는 state


2.    state간의 전의를 표현하는 action


3.    state 전이에 나타나는 onEntry, onExit 함수


 

소스코드


Action(enum)

public enum Action {
   
EAT, DIGEST, GOTOBED;
}

 

State(enum)

public enum State {
   
HUNGRY{
       
public State act(Action action){
           
switch (action){
                
case EAT: return FULL;
               
default: return null;
            }
        }
    },
   
FULL{
       
public State act(Action action){
           
switch (action){
               
case EAT: return ANGRY;
               
case DIGEST: return HUNGRY;
               
case GOTOBED: return SLEEPING;
               
default: return null;
            }
        }
    },
   
ANGRY{
       
public State act(Action action){
           
switch (action){
               
case DIGEST: return FULL;
                
default: return null;
            }
        }
    },
   
SLEEPING{
       
public void onEntry(){
           
System.out.println("go bed");
        }
       
public State act(Action action){
           
return null;
        }
    };
   
abstract State act(Action action);
   
public static State getInitState(){
       
return HUNGRY;
    }
   
public static boolean isFinalState(State state){
       
return state==SLEEPING;
    }
   
public void onEntry(){}
   
public void onExit(){}
}

 

StateContext(class)

public class StateContext {
   
private State currentState;
   
public StateContext(){
       
currentState = State.getInitState();
    }
   
public void processEvent(Action action){
       
State next= currentState.act(action);
       
if(next != null){
            
currentState.onExit();
           
System.out.println(action +"에 의해 State " +
                   
currentState+"에서 "+next+"로 바뀜");
           
currentState=next;
           
currentState.onEntry();
           
if(State.isFinalState(currentState)){
               
System.out.println("i'm final State");
            }
        }
else{
           
System.out.println(action+" state " +currentState
           
+"에서는 의미 없는 짓");
        }
    }
}

 

Main

public class Main {
   
public static void main(String[] args){
       
StateContext context = new StateContext();
       
context.processEvent(Action.EAT);
       
context.processEvent(Action.EAT);
       
context.processEvent(Action.GOTOBED);
       
context.processEvent(Action.DIGEST);
       
context.processEvent(Action.EAT);
       
context.processEvent(Action.GOTOBED);
       
context.processEvent(Action.DIGEST);
       
context.processEvent(Action.GOTOBED);
    }
}



결과




UML