[Design Pattern] State Pattern
25 Jan 2018State Pattern
상태에 따라 기능이 다르게 동작해야 할 때 사용할 수 있는 패턴
예시 상황
자판기 프로그램 구현
public class VendingMachine {
// NOCOIN: 동전이 없는 상태
// SELECTABLE: 동전이 투입되어 제품을 선택할 수 있는 상태
public static enum State { NOCOIN, SELECTABLE }
private State state = State.NOCOIN;
// 동전이 투입되었을 때 동작
public void insertCoin(int coin) {
switch (state) {
case NOCOIN:
increaseCoin(coin);
state = State.SELECTABLE;
break;
case SELECTABLE:
increaeCoin(coin);
}
}
// 제품을 선택했을 때 동작
public void select(int productId) {
switch (state) {
case NOCOIN:
// 아무 것도 하지 않음
break;
case SELECTABLE:
provideProduct(productId);
decreaseCoin();
if (hasNoCoin()) {
state = State.NOCOIN;
}
}
}
}
추가 요구 사항
- 자판기에 제품이 없는 경우 동전을 넣으면 바로 동전을 돌려준다.
public class VendingMachine {
// NOCOIN: 동전이 없는 상태
// SELECTABLE: 동전이 투입되어 제품을 선택할 수 있는 상태
// SOLDOUT: 제품이 없는 경우
public static enum State { NOCOIN, SELECTABLE, SOLDOUT }
private State state = State.NOCOIN;
// 동전이 투입되었을 때 동작
public void insertCoin(int coin) {
switch (state) {
case NOCOIN:
increaseCoin(coin);
state = State.SELECTABLE;
break;
case SELECTABLE:
increaeCoin(coin);
break;
// SOLDOUT이 추가됨
case SOLDOUT:
returnCoin();
break;
}
}
// 제품을 선택했을 때 동작
public void select(int productId) {
switch (state) {
case NOCOIN:
// 아무 것도 하지 않음
break;
case SELECTABLE:
provideProduct(productId);
decreaseCoin();
if (hasNoCoin()) {
state = State.NOCOIN;
}
break;
// SOLDOUT이 추가됨
case SOLDOUT:
// 아무 것도 하지 않음
break;
}
}
}
상태 패턴 적용
동전 증가 처리와 제품 선택 처리를 할 수 있는 인터페이스를 제공하고 콘크리트 클래스에서 기능을 구현한다.
상태 패턴을 적용한 VendingMachine 구현
public class VendingMachine {
private State state;
public VendingMachine() {
state = new NoCoinState();
}
public void insertCoin(int coin) {
state.increaseCoin(coin, this);
}
public void select(int productId) {
state.select(productId, this);
}
public void changeState(State newState) {
this.state = newState;
}
}
동전 증가 처리와 제품 선택 처리를 할 수 있는 두 개의 메서드를 정의하고 있는 State 인터페이스
interface State {
public void increaseCoin(int coin, VendingMachine vm);
public void select(int productId, VendingMachine vm);
}
동작 없음 상태일 때의 동작을 구현한 NoCoinState 클래스
public class NoCoinState implements State {
@Override
public void increaseCoin(int coin, VendingMachine vm) {
vm.increaseCoin(coin);
vm.changeState(new SelectableState());
}
@Override
public void select(int productId, VendingMachine vm) {
SoundUtil.beep();
}
}
음료 가능 상태의 동작을 구현한 SelectableState 클래스
public class SelectableState implements State {
@Override
public void increaseCoin(int coin, VendingMachine vm) {
vm.increaseCoin(coin);
}
@Override
public void select(int productId, VendingMachine vm) {
vm.provideProduct(productId);
vm.decreaseCoin();
if (vm.hasNoCoin()) {
vm.changeState(new NoCoinState());
}
}
}