행동 (3) - 상태(State) 패턴
- 객체의 상태에 따라 처리를 다르게 하는 패턴
- 상태 패턴을 사용하면 상태에 따라 캡슐화 된 다른 클래스를 사용하기 때문에 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있다
용어
- State : 상태 인터페이스
- Concrete State : 각 상태에 따른 처리 클래스
- Context : State를 사용하는 객체
구현
- State
- 상태를 별도의 클래스로 캡슐화
public interface ElevatorState {
public void pushUpButton();
public void pushDownButton();
public void pushStopButton();
}
- Concrete State
public class UpState implements ElevatorState {
@Override
public void pushUpButton() {
System.out.println("XXX");
}
@Override
public void pushDownButton() {
System.out.println("Down!!");
}
@Override
public void pushStopButton() {
System.out.println("Stop!!");
}
}
public class DownState implements ElevatorState {
@Override
public void pushUpButton() {
System.out.println("Up!!");
}
@Override
public void pushDownButton() {
System.out.println("XXX");
}
@Override
public void pushStopButton() {
System.out.println("Stop!!");
}
}
public class StopState implements ElevatorState {
@Override
public void pushUpButton() {
System.out.println("Up!!");
}
@Override
public void pushDownButton() {
System.out.println("Down!!");
}
@Override
public void pushStopButton() {
System.out.println("XXX");
}
}
- Context
- 클라이언트로 부터 실행을 요청 받고 상태 객체에 처리를 위임한다
- 요청을 처리하고 상태를 변경시킨다
public class Elevator {
private ElevatorState elevatorState;
public Elevator() {
elevatorState = new StopState();
}
private void setState(ElevatorState state) {
this.elevatorState = state;
}
public void pushUpButton() {
elevatorState.pushUpButton();
setState(new UpState());
}
public void pushDownButton() {
elevatorState.pushDownButton();
setState(new DownState());
}
public void pushStopButton() {
elevatorState.pushStopButton();
setState(new StopState());
}
}
- Client
public class Main {
public static void main(String[] args) {
Elevator elevator = new Elevator();
elevator.pushUpButton();
}
}
장점
- 상태에 따른 동작을 개별 클래스로 옮겨 관리할 수 있다
- 기존의 특정 상태에 따른 동작을 변경하지 않고 새로운 상태에 다른 동작을 추가할 수 있다 [OCP]
단점
- 복잡도가 증가한다
상태 패턴 vs 전략 패턴
- 상태
- 상황에 따라 여러 상태 객체 중 한 객체에게 모든 행동을 맡겨 자연스럽게 객체가 바뀐다
- 클라이언트는 상태 객체를 몰라도 된다
- 전략
- 클라이언트가 Context 객체에세 어떤 전략 객체를 사용할지 지정해준다