문제 및 이론 정리/디자인패턴

[디자인패턴] State - 상태를 클래스로 표현한다

hail2y 2025. 2. 25. 11:00

책 [JAVA 언어로 배우는 디자인 패턴 입문 3판;유키 히로시 저]을 참고하여 작성하였습니다. 

 

상태를 클래스로 표현한다.

클래스를 전환함으로써 상태 변화를 나타낸다.

 

State 상태마다 다르게 동작하는 인터페이스(API) 정의, 상태에 의존한 동작을 하는 메서드 모음

ConcreteState State 인터페이스를 구현한 구체 클래스, 상태 클래스 ex. 주간 클래스, 야간 클래스

Context 현재 상태를 나타내는 ConcreteState를 필드로 둔다, 이 필드에 상태 클래스의 인스턴스를 대입함으로써 상태를 전환한다 

 

 

1. State 패턴을 사용하지 않는 코드 예시

경비 시스템 클래스 {
    금고 사용 시 호출되는 메소드() {
    	if(주간) {
        	...
        } else if (야간) {
        	...
        }
    }
    
    일반 통화 사용 시 호출되는 메소드() {
    	if(주간) {
        	...
        } else if (야간) {
        	...
        }
    }
}

 

2. State 패턴을 사용한 코드 예시 - 상태가 클래스로 표현되어 상태를 체크하는 if문이 아예 등장하지 않는다.

주간 상태를 표현하는 클래스 {
    금고 사용 시 호출되는 메서드 {
    	...
    }
    
    일반 통화 시 호출되는 메서드 {
    	...
    }
}
야간 상태를 표현하는 클래스 {
    금고 사용 시 호출되는 메서드 {
    	...
    }
    
    일반 통화 시 호출되는 메서드 {
    	...
    }
}

 

  • 분할정복(divide and conquer) - 클래스로 상태를 표현함으로써 문제를 분할한다. 클래스로 표현하지 않았다면 처리 메서드마다 조건 분기를 써야 했다.
  • 상태 (인터페이스)에 의존한 처리 - Main에서 setClock()을 호출하여 시간을 설정하면 현재 시간에 따른 상태 클래스의 doClock()이 호출된다. 즉 상태에 따라 동작이 달라지는 처리고, 다형성을 이용했다.
  • 여기서는 상태 전환을 상태에 의존하는 동작으로 생각해 각 상태 클래스에서 처리했다. doClock()에서 자기의 상태에 맞지 않으면 상태 전환을 시도하는데 이때 다른 구체 클래스 정보를 직접 입력했다. 다른 구체 클래스 간 의존 관계가 깊어진다는 단점이 있지만 다른 상태로 언제 전환하는지 알 수 있다는 장점이 있다. 다른 상태 클래스가 또 추가된다면 상태 전환에 대해서 주의 깊게 설계해야 한다. 
// Context 인터페이스를 구현한 클래스 중 changeState()
// 시간 설정
@Override 
public void setClock(int hour) [
    String clockString = String.format("현재 시간은 %02d:00", hour);
    System.out.println(clockString);
    textClock.setText(clockString);
    state.doClock(this, hour);
}


// 상태 전환

@Override
public void changeState(State state) {
    System.out.println(this.state + "에서" + state + "으로 상태가 변화했습니다.");
    this.state = state;
}
@Override
public void doClock(Context, int hour) { // 주간 클래스
    if(hour < 9 || 17 <= hour) {
        context.changeState(NightState.getInstance());
    }
}

@Override
public void doClock(Context context, int hour) { // 야간 클래스
    if(9 <= hour && hour < 17) {
    	context.changeState(DayState.getInstance());
    }
}