# 상태 (State) 패턴
# 상태 패턴이란 무엇인가요?
TIP
객체 내부 상태 변경에 따라 객체의 행동이 달라지는 패턴.
- 상태에 특화된 행동들을 분리해 낼 수 있으며, 새로운 행동을 추가하더라도 다른 행동에 영향을 주지 않는다.
- State - Context가 변경될 수 있는 상태에 대한 공통된 인터페이스이며, 추상 클래스이든 인터페이스이든 추상체로서 반드시 존재해야 한다.
- Context - 상태 변경이 이루어지는 객체, 고유한 정보를 담고 있을 수 있음.
- ConcreteState - 상태에 따라 달라지는 operation을 정의
즉, 객체의 특정 상태를 클래스로 선언하고, 클래스에서는 해당 상태에서 할 수 있는 행위들을 메서드로 정의한다.
그리고 이러한 각 상태 클래스들을 인터페이스로 캡슐화하여, 클라이언트에서 인터페이스를 호출하는 방식을 말한다.
# 상태 패턴을 적용해보자.
- 여기에 TV가 있는데, 리모콘의 전원버튼을 누르면 꺼져있는 상태에서는 켜지고, 켜져있는 상태에서는 꺼진다.
- 즉, 상태에 따라 행동이 달라지는 간단한 예시로 볼 수 있다.
public class TV {
private State powerState = State.OFF;
public enum State {
ON, OFF
}
public void powerPush() {
if (powerState == State.ON) {
System.out.println("전원 off");
powerState = State.OFF;
} else {
System.out.println("전원 on");
powerState = State.ON;
}
}
}
다음처럼 상태에 따른 분기문이 발생하게 되고, 이는 상태의 확장을 어렵게 만든다.
public interface PowerState {
public void powerPush(TV tv);
}
- 상태를 위한 인터페이스를 만든다.
public class Off implements PowerState {
@Override
public void powerPush(TV tv) {
System.out.println("전원 on");
tv.setPowerState(new ON());
}
}
public class On implements PowerState {
@Override
public void powerPush(TV tv) {
System.out.println("전원 off");
tv.setPowerState(new OFF());
}
}
public class TV {
private PowerState powerState;
public TV() {
this.powerState = new Off();
}
public void setPowerState(PowerState powerState) {
this.powerState = powerState;
}
public void powerPush() {
powerState.powerPush();
}
}
# 상태 패턴의 장점과 단점은?
장점
- 상태에 따른 동작을 개별 클래스로 옮겨서 관리할 수 있다.
- 기존의 특정 상태에 따른 동작을 변경하지 않고 새로운 상태에 다른 동작을 추가할 수 있다.
- 코드 복잡도를 줄일 수 있다.
단점
- 복잡도가 증가한다.
# 상태 패턴의 예시
- 주로 비지니스 로직에서 작성되는 코드이기 때문에 실질적인 사용 예시는 자바 스프링에서 찾아보기 힘들다.
javax.faces.lifecycle.LifeCycle#execute()
# 출처
- https://kingchan223.tistory.com/323
- https://victorydntmd.tistory.com/294
- https://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries/2707195#2707195