스테이트 패턴(State Pattern) 예제

개선할 샘플 코드

reference code to refactor

위의 예제는 현재 상태에 따라서 수행하는 동작이 달라지는 Gumball Machine을 구현한 것입니다.

각 메소드는 아래와 같이 현재 상태에 따라서 수행하는 동작이 달라지게 됩니다.

GumballMachine.java

	public void insertQuarter() {
	      switch (state) {
	          case SOLD_OUT:
	              System.out.println("SOLD OUT");
	              break;
	          case NO_QUARTER:
	              state = HAS_QUARTER;
	              System.out.println("Inserted quarter");
	              break;
	          case HAS_QUARTER:
	              System.out.println("Please insert only one quarter");
	              break;
	          case SOLD:
	              System.out.println("Please wait for a second. The gumball is going out");
	              break;
	      }
	  }

샘플 코드의 문제점

  • OCP(Open Closed Principal)을 지키지 않고 있습니다.
  • 객체 지향 디자인이라고 하기 힘듭니다.
  • 상태 전환이 복잡한 조건문 속에 숨어 있기 때문에 분명하게 드러나지 않습니다.
  • 바뀌는 부분을 전혀 캡슐화하지 않았습니다.
  • 다른 기능을 더 추가하는 과정에서 기존 코드에 없던 새로운 버그가 생길 가능성이 높습니다.

스테이트 패턴(State Pattern) 적용

reference code

스테이트 패턴을 적용하면 아래와 같이 적용할 수 있습니다.

GumballMachine.java

public class GumballMachine {

    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;
    State winnerState;

		// 현재 state
    State state = soldOutState;
    int count;

		...

		public void insertQuarter() {
        state.insertQuarter();
    }

		...
}

NoQuaterState.java

@Override
    public void insertQuarter() {
        System.out.println("Inserted quarter");
        machine.setState(machine.getHasQuarterState());
    }

위의 코드처럼 기존에는 if 문으로 모든 상태에 대해 각 행동을 정해줘야했지만, 이제 State 클래스에서 각 상태에 맞게 동작을 수행하고 상태를 변경해줍니다.

구현을 구조적으로 바꾸면서 크게 아래 다섯 가지 이점을 얻을 수 있었습니다.

  • 각 상태의 행동을 별개의 클래스로 국지화시켰습니다.
  • 관리하기 힘든 골칫덩어리 if 선언문들을 없앴습니다.
  • 각 상태를 변경에 대해서는 닫혀 있도록 하면서도 GumballMachine 자체는 새로운 상태 클래스를 추가하는 확장에 대해서 열려있도록 고쳤습니다. (OCP)
  • 더 이해하기 좋은 코드 베이스와 클래스 구조를 만들었습니다.

스테이트 패턴(State Pattern)의 정의

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

profile
재밌는 것만 하고 싶어 ʕ•ﻌ•ʔ

0개의 댓글