티스토리 뷰
State 패턴이란?
- 객체의 상태에 따라 바뀌는 행위를 캡슐화 한 패턴.
- 상태에 따라 if, else 조건문으로 분기하는 부분을 제거하여 simple한 코드를 구성할 수 있다.
예제
강아지 육성 프로그램(다마고치)을 만들어보자.
사용자는 강아지에게 밥을 주거나, 놀아주는 2가지 행위를 할 수 있다.
그리고 강아지는 GOOD, HUNGRY, BORED 3가지 상태를 가지고, 상태에 따른 다른 행동을 한다.
- GOOD : 배고프지도, 심심하지도 않은 상태.
- HUNGRY : 배고픈 상태
- BORED : 심심한 상태
public class Damagochi {
private static final int GOOD = 0; // 좋은 상태
private static final int HUNGRY = 1; // 배고픈 상태
private static final int BORED = 2; // 심심한상태
private int state = GOOD;
// 현재 상태를 저장.
public void setState(int state) {
this.state = state;
}
// eat action에 대한 상태별 행위
public void eat() {
if (state == HUNGRY) {
System.out.println("맛있다 오예^^"); // 배고플 때는 맛있게 먹음. GOOD으로 상태 변경
setState(GOOD);
} else if (state == GOOD) {
System.out.println("점점 심심해져요..."); // 배부를 때는 심심해짐. BORED로 상태 변경
setState(BORED);
} else if (state == BORED) { // 지루할 때는 놀아다라고 요청. 상태변경 없음.
System.out.println("놀아주세요ㅠㅠ");
}
}
// play action에 대한 상태별 행위
public void play() {
if (state == BORED) { // 지루할 때는 신나함. GOOD으로 상태 변경
System.out.println("신난다 오예^^");
setState(GOOD);
} else if (state == GOOD) {
System.out.println("점점 배고파 져요..."); // 심심하지 않을 때는 배고파짐. HUNGRY로 상태 변경
setState(HUNGRY);
} else if (state == HUNGRY) {
System.out.println("밥 주세요ㅠㅠ"); // 배고플 때는 밥달라고 요청. 상태변경 없음.
}
}
}
문제점
- 상태에 따른 조건문이 많아서 code 가독성이 떨어지고 복잡함.
- 상태가 많아지거나 eat(), play() 외의 기능 추가 될 수록 조건문 추가 되므로 복잡해 지고 유지보수에 어려움이 있음.
state 패턴을 적용하여 상태를 class로 바꿔 보자.
public class Damagochi {
// 각각의 Status class
private GoodState goodState;
private HungryState hungryState;
private BoredState boredState;
private State currentState;
public Damagochi() {
goodState = new GoodState(this);
hungryState = new HungryState(this);
boredState = new BoredState(this);
// 초기 State는 GOOD
currentState = goodState;
}
public void setState(State state) {
this.currentState = state;
}
public State getGoodState() {
return goodState;
}
public State getHungryState() {
return hungryState;
}
public State getBoredState() {
return boredState;
}
// eat action에 대한 행위를 현재 State에게 위임
public void eat() {
currentState.eat();
}
// play action에 대한 행위를 현재 State에게 위임.
public void play() {
currentState.play();
}
}
public abstract class State {
public Damagochi context;
public State(Damagochi context) {
this.context = context;
}
abstract void eat();
abstract void play();
}
public class GoodState extends State{
public GoodState(Damagochi context) {
super(context);
}
@Override
void eat() {
System.out.println("점점 심심해져요...");
context.setState(context.getBoredState());
}
@Override
void play() {
System.out.println("점점 배고파져요...");
context.setState(context.getHungryState());
}
}
public class HungryState extends State{
public HungryState(Damagochi context) {
super(context);
}
@Override
void eat() {
System.out.println("맛있다 오예^^");
context.setState(context.getGoodState());
}
@Override
void play() {
System.out.println("밥 주세요ㅠㅠ");
}
}
public class BoredState extends State{
public BoredState(Damagochi context) {
super(context);
}
@Override
void eat() {
System.out.println("놀아주세요ㅠㅠ");
}
@Override
void play() {
System.out.println("신난다. 오예^^");
context.setState(context.getGoodState());
}
}
위 처럼 구현 시, 기존 Damagochi class (Context)의 조건문이 모두 사라지고, 각각의 State 객체에게 행위를 위임하고 있다.
상태가 추가되더라도 상태클래스를 추가하여 해당 상태에 맞는 구현을 code를 구현하면 된다.
'Programing > DesignPattern' 카테고리의 다른 글
Factory Method 패턴 (0) | 2016.10.05 |
---|---|
GOF 디자인 패턴 (0) | 2016.10.04 |
Template Method 패턴 (0) | 2016.08.30 |
Composite 패턴 (0) | 2016.08.24 |
Singleton 패턴 (0) | 2016.08.24 |
댓글