• 객체의 상태에 따라 처리를 다르게 하는 패턴
  • 상태 패턴을 사용하면 상태에 따라 캡슐화 된 다른 클래스를 사용하기 때문에 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있다

용어

image

  • 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();
    }
}

장점

  1. 상태에 따른 동작을 개별 클래스로 옮겨 관리할 수 있다
  2. 기존의 특정 상태에 따른 동작을 변경하지 않고 새로운 상태에 다른 동작을 추가할 수 있다 [OCP]

단점

  1. 복잡도가 증가한다

상태 패턴 vs 전략 패턴

  • 상태
    • 상황에 따라 여러 상태 객체 중 한 객체에게 모든 행동을 맡겨 자연스럽게 객체가 바뀐다
    • 클라이언트는 상태 객체를 몰라도 된다
  • 전략
    • 클라이언트가 Context 객체에세 어떤 전략 객체를 사용할지 지정해준다