스테이트 패턴

스테이트 패턴이란, 객체 내부 상태에 따라 객체의 행동이 바뀌는 것이다.

뽑기 기계가 있다고 하자. 사람은 이 기계에 동전을 넣고 손잡이를 돌리면 뽑기기계의 상품을 받게 된다.  기계의 입장에선 동전이 있고 없고의 상태를 가질 수 있다. (설명을 쉽게 하기 위해 행동과 상태를 제한하였다.)

위에서 동전이 있고, 없고는 상태이며, 동전을 넣고 손잡이를 돌리는건 행동이 된다.
이를 간단하게 구현해보면 아래와 같다. state 상태에 따라 동전을 넣고 손잡이를 돌리는 행동에 대해 다르게 동작한다.

public class gamble {
 final static int NO_COIN = 0;
 final static int HAS_COIN = 1;
 
 int state = NO_COIN; // 초기상태는 동전이 없음 
 
 public void insertCoin() {
  if(state == NO_COIN) {
   System.out.println('동전을 넣으셨습니다.');
   state = HAS_COIN;
  }
  else if(state == HAS_COIN) {
   System.out.println('동전이 이미 있습니다..');
  }
 }
 
 public void turnHandle() {
  if(state == NO_COIN) {
   System.out.println('동전을 넣어주세요.');
  }
  else if(state == HAS_COIN) {
   System.out.println('상품이 나옵니다.');
   state = NO_COIN;
  }
 }
}
위의 구조에서는 문제가 없지만, 개발해야할 제품의 상태(NO_COIN 과 같은)와 행동(InsertCoin)이 많아질수록 변화에 유연하지 않는다. 이 때, 사용할 수 있는 패턴이 스테이트 패턴이다.

위 예를 스테이트 패턴으로 바꾸어보자.
우선 행동에 대한 메소드가 들어있는 인터페이스를 정의한다. (여기선 state 인터페이스)
다음은 state를 구현하는 상태 class를 만든다. 여러 상태가 있다면, 각 상태에 해당하는 class를 구현한다.


public class gamble {
 state hasCoin;
 state noCoin;
 
 state s = noCoin; // 초기상태는 동전이 없음 
 
 public gamble() {
  hasCoin = new HasCoin(this);
  noCoin = new NoCoin(this);
 }
 
 public setState(State s) {
  this.s = s;
 }
 public void insertCoin() {
  s.insertCoin();
 }
 public void turnHandle() {
  s.turnHandle();
 }
 // getter 메소드...
}

public interface state {
 void insertCoin();
 public void turnHandle();
}

public class HasCoin implements state {
 gamble g;
 
 public HasCoin(gamble g) {
  this.g = g;
 }
 
 public void insertCoin() {
  System.out.println('동전이 이미 있습니다..');
 }
 public void turnHandle() {
  System.out.println('상품이 나옵니다.');
  g.setState(gamble.getNoCoinState());
 }
}

public class NoCoin implements state {
 gamble g;
 
 public NoCoin(gamble g) {
  this.g = g;
 }
 
 public void insertCoin() {
  System.out.println('동전을 넣으셨습니다.');
  g.setState(gamble.getHasCoinState());
 }
 public void turnHandle() {
  System.out.println('동전을 넣어주세요.');
 }
}

댓글 없음:

댓글 쓰기