스테이트 패턴: 상태를 캡슐화하는 패턴
상태 머신 다이어그램: 상태와 상태 변화를 모델링하는 도구
(상태: 객체가 가질 수 있는 어떤 조건이나 상황)
기존 코드: 형광등의 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("반응 없음"); } }