suyeonme

[디자인패턴] 상태 패턴(State Pattern) 본문

프로그래밍👩🏻‍💻/디자인 패턴

[디자인패턴] 상태 패턴(State Pattern)

suyeonme 2022. 8. 9. 11:07
헤드 퍼스트 디자인 패턴을 읽고 정리한 내용입니다.

상태 패턴(State Pattern)이란?


상태 패턴을 사용하면 객체의 내부 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있다. 마치 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있다.

이미지출처: https://www.tutorialspoint.com/design_pattern/images/state_pattern_uml_diagram.jpg

 

상태 패턴을 사용하지 않은 경우


뽑기 기계를 구현하는 코드이다.

문제점

  • 코드에 대한 수정이 필요한 경우, 각각의 상태에 의존하는 모든 코드를 모두 고쳐야한다. 
  • 상태가 변화함에 따라서 조건문이 복잡해진다. 
public class GumballMachine {
  final static int SOLD_OUT = 0;
  final static int NO_QUATER = 1;
  final static int HAS_QUATER = 2;
  final static int SOLD = 3;
  
  int state = SOLD_OUT;
  int count = 0;
  
  public GumballMachine(int count) {
    this.count = count;
    if(count > 0) {
      state = NO_QUATER;
    }
  }
  
  public void insertQuater() {
    if(state == HAS_QUATER) {
      System.out.println("동전은 한개만 넣어주세요.");
    } else if(state == NO_QUATER) {
      System.out.println("동전은 한개만 넣으셨습니다.");
    } else if(state == SOLD_OUT) {
      System.out.println("매진되었습니다. 다음 기회에 이용해주세요.");
    } else if(state == SOLD) {
      System.out.println("알맹이를 내보내고있습니다.");
    }
  }
  
  public void ejectQuater() {//...}
  public void turnCrank() {//...}
  public void dispense() {//...}
}

상태패턴 예제


State 클래스 생성

필요한 상태(SOLD_OUT, NO_QUATER, HAS_QUATER, SOLD)에 해당하는 state 클래스를 생성한다.

public interface state {
  public abstract void insertQuater();
  public abstract void ejectQuater();
  public abstract void turnCrank();
  public abstract void dispense();
}

public clss NoQuaterState implements State() {
  GumballMachine gumballMachine;
  
  public NoQuaterState(GumballMachine gumballMachine) {
    this.gumballMachine = gumballMachine;
  }
  
  public void insertQuater() {
    System.out.println("동전을 넣었습니다.");
    gumballMachine.setState(gumballMachine.getHasQuaterState()); // 상태 변경
  }
  
  public void ejectQuater() {
    System.out.println("동전을 넣어주세요.");
  }
  
  public void turnCrank() {
    System.out.println("동전을 넣어주세요.");
  }
  
  public void dispense() {
    System.out.println("동전을 넣어주세요.");
  }
}

뽑기 기계 코드 

상태 변경 및 각 state에 따른 행동은 state 클래스에서 수행한다.

public class GumballMachine {
  State soldOutState;
  State noQuaterState;
  State hasQuaterState;
  State soldState;

  State state;
  int count = 0;
  
  public GumballMachine(int numberGumballs) {
    State soldOutState = new SoldOutState();
    State noQuaterState = new NoQuaterState();
    State hasQuaterState= new HasQuaterState();
    State soldState = new SoldState();
  
    this.count = numberGumballs;
    if(numberGumballs > 0) {
      state = noQuaterState;
    } else {
      state = soldState;
    }
  }
  
  public void insertQuater() {
    state.insertQuater();
  }
  
  public void ejectQuater() {
    state.ejectQuater();
  }
  
  public void turnCrank() {
    state.turnCrank();
  }
  
  public void dispense() {
    state.dispense();
  }
  
  void setState(State state) {
    this.state = state;
  }
}

전략 패턴(Strategy Pattern) vs 상태 패턴(State Pattern)


전략 패턴(Strategy Pattern) 

  • 클라이언트가 Context 객체에게 어떤 전략 객체를 사용할지 지정해준다. (특정 클래스의 인스턴스를 만들고 그 인스턴스에게 전략 객체를 넘겨준다)
  • 주로 실행시에 전략 객체를 변경할 수 있는 유연성을 제공하는 용도로 사용된다. (서브 클래스를 만드는 방법을 대신한다)

상태 패턴(State Pattern)

  • 상태 객체에 일련의 행동이 캡슐화 된다. 상황에 따라 Context 객체에서 여러 상태 객체중 한 객체에게 행동을 맡긴다. 
  • Context 객체에 수많은 조건문을 넣는 대신 상태 패턴을 사용할 수 있다.
Comments