상태 패턴이란?
위키백과
객체 지향 방식으로 상태 기계를 구현하는 행위 소프트웨어 디자인 패턴이다. 상태 패턴을 이용하면 상태 패턴 인터페이스의 파생 클래스로서 각각의 상태를 구현함으로써, 또 패턴의 슈퍼클래스에 의해 정의되는 메소드를 호출하여 상태 변화를 구현함으로써 상태 기계를 구현한다.
특징
•
전략 패턴의 친척이다.
•
상태에 따른 움직임을 구현한다.
우리가 자판기를 만든다고 생각해보자. 자판기의 모든 가격은 동일하고, 판매하는 음료도 모두 똑같다. 빨리 만들어 돌라고 상사가 부탁했다. 그래서 엄청 난 코딩 실력을 가진 나는 후따닥 만들어줬다.
요구 사항
- 100원 자판기 (모든 자판기의 음료는 동일한 금액)
- 동일한 음료가 판매된다.
코드로 보기
상태 패턴을 적용 전
만들고 나서 상사에게 코드를 전달했다. 그런데 일부 문구를 바꿔야한다. 그래서 봤더니 코드가 이 모양으로 되어 있다.
public class VendingMachine {
// 상태 변화시에 비교 값
static final int SOLD_OUT = 0; // 모두 판매
static final int NO_QUARTER = 1; // 동전 없음 -> 들어온 돈
static final int HAS_QUARTER = 2; // 동전 있음 -> 들어온 돈
static final int SOLD = 3; // 판매
int state = SOLD_OUT;
int count = 0;
public VendingMachine(int count) {
this.count = count;
this.state = this.count > 0 ? NO_QUARTER : this.state;
}
public void insetQuarter() {
switch (state){
case HAS_QUARTER:
System.out.println("동전을 하나만 넣어주세요");
break;
case NO_QUARTER:
state = HAS_QUARTER;
System.out.println("동전을 넣으셨습니다.");
break;
case SOLD_OUT:
System.out.println("매진 되었습니다. 다음 기회에 이용해 주세요");
break;
case SOLD:
System.out.println("음료를 뽑는 중 입니다.");
break;
default:
throw new UnsupportedOperationException("오류 입니다.");
}
}
public void ejectQuarter() {
... swich case
}
public void pressButton() {
... swich case
}
public void dispense() {
... swich case
}
}
Line 100
Java
복사
상태 패턴을 적용 후
상태패턴을 적용한 이후의 클래스 다이어그램이다. 또한 팩토리까지 만들어서 상태들을 넣어준다. 이렇게 만드니 코드가 엄청나게 깔끔해졌다. 상태패턴에서 가장 많은 변화가 생기는 것은 클래스 다이어그램이라고 생각한다. 기존 하나의 클래스에 상태들이 모여있기에 너무 클래스가 무거워지고, 많은 분기가 생긴다. 하지만 이렇게 상태를 분리하여, 알고리즘화 시키면 다음과 같이 상태를 한눈에 알아볼 수 있게 된다.
code
여기서 궁금증 기존 다이어그램이 더 쉬운데? 라고 느낄 수 있다. 하지만 자판기 클래스가 하는 일과 상태를 전부 나열하여 보여주지 못한다. 즉, 클래스 다이어그램에 너무 적은 정보가 생기고 그만큼 하나의 자판기가 너무 많은 일을 하고 있는 슈퍼클래스가 되는 것이다. 하지만 반대로 상태 패턴을 보면 어떤가 자판기가 저런 상태들을 가지고 있는 것을 바로 알 수 있다. 또한 상태명, 상태들의 메서들만 보고도 어떤 행동을 할지 예측할 수 있다. 또한 다른 상태가 추가될 때 간단하게 State를 상속 받기만 하면 된다.
기존
상태 패턴 적용 후
상태 패턴 이해하기
상태 패턴이란?
위키백과
객체 지향 방식으로 상태 기계를 구현하는 행위 소프트웨어 디자인 패턴이다. 상태 패턴을 이용하면 상태 패턴 인터페이스의 파생 클래스로서 각각의 상태를 구현함으로써, 또 패턴의 슈퍼클래스에 의해 정의되는 메소드를 호출하여 상태 변화를 구현함으로써 상태 기계를 구현한다.
•
전략 패턴의 친척이다.
•
상태에 따른 움직임을 구현한다.
Context - 자판기
State - abstract State
ConcreteStateA, B - SoldState, SoldOutState, NoQuarterState, HasQuarterState
재미있는 점
본 예제에서는 팩토리를 이용하여 상태들을 자판기에 넣어준다. 근데 왜 그런 귀찮은 일을 할까? 바로 직접적인 의존을 피하게 만들기 위해서 이다. 다음과 같이 자판기 클래스는 모든 상태들과 직접적인 연관관계가 생긴다. 이렇게 되면 직접적으로 구현된 상태의 변경이 일어날 때 자판기에 영향을 줄 수 있다. 그래서 팩토리에게 생성 책임을 넘겨버리는 것이다. 그러면 자판기 입장에서는 Abstract State Class 만 바라보기 때문에 Abstract State Class가 변경되지 않는 이상 변경할 일이 거의 없어진다.
상태 패턴 적용(팩토리)
상태 패턴 적용(비팩토리)