
스테이트 패턴(State Pattern) 예제
개선할 샘플 코드
위의 예제는 현재 상태에 따라서 수행하는 동작이 달라지는 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) 적용
스테이트 패턴을 적용하면 아래와 같이 적용할 수 있습니다.
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)을 이용하면 객체의 내부 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있습니다. 마치 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있습니다.
반응형
'Design Patterns' 카테고리의 다른 글
Head First Design Patterns 14. Compound Pattern (0) | 2022.03.25 |
---|---|
Head First Design Patterns 13. Proxy Pattern (0) | 2022.03.19 |
Head First Design Patterns 11. Composite Pattern (0) | 2022.03.13 |
Head First Design Patterns 10. Iterator Pattern (0) | 2022.03.12 |
Head First Design Patterns 9. Adapter Pattern (0) | 2022.03.11 |