스테이트 패턴: 상태를 캡슐화하는 패턴
상태 머신 다이어그램: 상태와 상태 변화를 모델링하는 도구
(상태: 객체가 가질 수 있는 어떤 조건이나 상황)
기존 코드: 형광등의 ON버튼을 누르면 켜지고, OFF 버튼을 누르면 꺼지는 코드

class Light{
private static int ON=0;
private static int OFF=1;
private int state;
public Light() {
state=OFF;
}
public void on_button_pushed() {
if(state==ON) {
System.out.println("반응 없음");
}
else {
System.out.println("Light On!");
state=ON;
}
}
public void off_button_pushed() {
if(state==OFF) {
System.out.println("반응 없음");
}
else {
System.out.println("Light Off!");
state=OFF;
}
}
}
public class Client{
public static void main(String[] args) {
Light light=new Light();
light.off_button_pushed();
light.on_button_pushed();
light.off_button_pushed();
}
}
문제점: 새로운 상태인 ‘Sleeping’이 오면 기존 코드를 수정해야 된다. 만약 상태가 한 개만 존재하면 조건문이 없었지만, 상태가 추가되면 조건문이 생겨 코드를 수정해야 된다. 이러한 조건문이 많으면 이해가 어렵다.
해결 방법: 각 상태(ex. ON, OFF)를 캡슐화하고, State라는 인터페이스를 만들어서 구현한다. Light는 State와 집합 관계를 가진다.

각 상태와 이 상태에 의존적인 행위를 하나의 클래스로 캡슐화한다.
-> OCP에 위배되지 않고, 조건문을 사용하지 않아 코드의 이해가 쉬워진다!
interface State{
public void on_button_pushed(Light light);
public void off_button_pushed(Light light);
}
class ON implements State{
public void on_button_pushed(Light light) {
System.out.println("반응 없음");
}
public void off_button_pushed(Light light) {
System.out.println("Light Off!");
light.setState(new OFF());
}
}
class OFF implements State{
public void on_button_pushed(Light light) {
System.out.println("Light ON!");
light.setState(new ON());
}
public void off_button_pushed(Light light) {
System.out.println("반응 없음");
}
}
class Light{
private State state;
public Light() {
state=new OFF();
}
public void setState(State state) {
this.state=state;
}
public void on_button_pushed() {
state.on_button_pushed(this);
}
public void off_button_pushed() {
state.off_button_pushed(this);
}
}
public class Client{
public static void main(String[] args) {
Light light=new Light();
light.off_button_pushed();
light.on_button_pushed();
light.off_button_pushed();
}
}
그런데 ON/OFF 객체를 계속해서 만들 필요가 없다!
-> 싱글톤 패턴으로 변경한다.
class OFF implements State{
private static OFF off=new OFF();
private OFF() {}
public static OFF getInstance() {
return off;
}
public void on_button_pushed(Light light) {
System.out.println("Light ON!");
light.setState(ON.getInstance());
}
public void off_button_pushed(Light light) {
System.out.println("반응 없음");
}
}