개발공부/디자인패턴

[디자인패턴] 스테이트 패턴(State Pattern)

키크니개발자 2022. 6. 25. 18:00

💡 코드가 보이지 않으시다면 드래그 혹은 오른쪽 아래 🌜 아이콘을 눌러 테마 색을 변경해주세요.

 

 

안녕하세요!

키크니 개발자 입니다. 🦒

 

스테이트 패턴이란?

객체의 내부 상태에 따라 스스로 행동을 변경할 수 있게 허가하는 패턴으로

이렇게 하면 객체는 마치 자신의 클래스를 바꾸는 것 처럼 보입니다. 

이 패턴을 사용하는 주된 목적은 상태 전이를 위한 조건 로직이 지나치게 복잡한 경우 이를 해소하는 것 입니다.

 

즉, 각 상태에 대응하는 별도의 클래스를 만들고 상태전이 로직을 그 클래스들로 옮기는 작업을 뜻합니다.

 

💡 상태 전이 로직이란?

객체의 상태와 이들 간의 전이 방법을 제어하는 것으로

클래스 내부 여기저기에 흩어져 존재하는 경향이 있습니다. 

스테이트 패턴의 장점은?

- if / else / switch를 효과적으로 제거할 수 있습니다.

- 클래스의 수가 취급해야 하는 상태의 수만큼 추가로 늘어난다는 점에 주의해야 하지만 이것은 상황에 따라 장점일 수도 있습니다.

- 상태가 많아지더라도 클래스의 개수는 증가하지만 코드의 복잡도는 증가하지 않기 때문에 유지 보수에 유리합니다.

스테이트 패턴의 단점은?

- 각각의 상태별로 똑같이 행동하는 메소드가 많다면 스테이트 패턴이 필요하지 않을 수 있습니다.

- 상태 변경 규픽이 여러 클래스에 분산되어 있기 때문에

상태 구현 클래스가 많아질 수록 상태 변경 규칙을 파악하기 어려워 질 수 있습니다.

전략 패턴(strategy pattern)과 스테이트 패턴(state pattern)과 다른점은?

코드를 보면 전략 패턴스테이트 패턴은 매우 유사한 것을 볼 수 있습니다.

Strategy Pattern은 어떤 동일한 틀 안에 있는 특정 작업의 방식이나 모드를 바꿔줄 때 사용합니다.

State Pattern특정 상태마다 다르게 할 일, 나아가서 그 상태들 자체를 그 상태마다 실행시 할 일과 함께 하나하나 모듈화해서 지정해둘 때 쓰입니다. (TV가 꺼져 있을 때 누르면 켜지고 켜진 상태에서 다시 누르면 꺼지는 버튼을 예시로 들 수 있습니다.)

 

💡전략 패턴은 여러 개의 버튼, 그리고 그 버튼들의 각각의 기능 사용, 스테이트 패턴은 하나의 버튼의 여러 상태로 이해했습니다.

쉽게 말하면,

Strategy Pattern이 모듈화 된 모드에 따라 다르게 실행되도록 하는 거라면,

State Pattern 그 메소드가 실행될 때 모드도 전환되도록 하는 것이라고 이해하면 좋습니다.

예시

상황

'얄팍한 코딩사전 : 객체지향 디자인패턴 1' 을 참고했습니다.

앱 화면의 다크 모드 여부를 켰다 껐다 하는 스위치를 프로그래밍 한 상황입니다.

public class MyProgram {

    public static void main(final String[] args) {

        final ModeSwitch modeSwitch = new ModeSwitch();

        modeSwitch.onSwitch(); // "FROM LIGHT TO DARK" 출력
        modeSwitch.onSwitch(); // "FROM DARK TO DARK" 출력
        modeSwitch.onSwitch(); // "FROM LIGHT TO DARK" 출력
        modeSwitch.onSwitch(); // "FROM DARK TO DARK" 출력

    }
}

앱 화면의 다크모드 여부를 켰다 껐다 할 수 있는 스위치를 실행하는 코드입니다.

같은 스위치(modeSwitch)로 onSwitch() 실행 하면 모드가 바뀌는 것을 확인할 수 있습니다.

public class ModeSwitch {

    private ModeState modeState = new ModeStateLight();  // (1)

    public void setModeState(ModeState modeState) {  // (2)
        modeState = modeState;
    }

    public void onSwitch() {  // (3)
        modeState.toggle(this);
    }
}

(1) 기본적으로 라이트모드(ModeStateLight) 설정이 되어있지만,

(2) setModeState로 Light 와 Dark로 변경할 수 있습니다.

(3) 버튼을 누르면(onSwitch() 실행하면) 현재 modeState 상태로 toggle(다른 값으로 전환) 되는 것을 확인할 수 있습니다. 

 

ModeSwitch 는 Strategy Pattern 의 SearchButton과 유사한 것을 볼 수 있습니다.

Strategy Pattern에는 private SearchStrategy searchStrategy = new SearchStrategyAll(); 이

State Pattern에서 private ModeState modeState = new ModeStateLight(); 과 유사한 것을 확인할 수 있고,

Strategy Pattern의 onClieck()은 State Pattern의 onSwitch()로 바뀐것을 확인할 수 있습니다.

더보기

public class SearchButton {
    
    MyProgram myProgram;
    
    public SearchButton(MyProgram myProgram) {
        myProgram = myProgram;
    }
 
    private SearchStrategy searchStrategy = new SearchStrategyAll(); // 1
    
    public void setSearchStrategy(SearchStrategy searchStrategy) { // 2
        searchStrategy = searchStrategy;
    }
 
    public void onClick() {
        searchStrategy.search();
    }
}

public interface ModeState {	// (1)
    public void toggle(ModeSwitch modeSwitch);
}

class ModeStateLight implements ModeState {	// (2)
    public void toggle(ModeSwitch modeSwitch) {
        System.out.println("FROM LIGHT TO DARK");
        // 화면을 어둡게 하는 코드
        // ..
        modeSwitch.setModeState(new ModeStateDark());	// (3)
    }
}

class ModeStateDark implements ModeState {	// (2)
    public void toggle(ModeSwitch modeSwitch) {
        System.out.println("FROM DARK TO LIGHT");
        // 화면을 밝게 하는 코드
        // ..
        modeSwitch.setModeState(new ModeStateLight());	// (3)
    }
}

(1) 인터페이스로 ModeState와 toggle(on/off를 바꿔주는 역할) 메소드를 구현하고

(2) 그것을 implements받은 ModeStateLight, ModeStateDark를 확인할 수 있습니다.

-> State Pattern은 Strategy Parttern의 모드 클래스처럼 스위치를 눌렀을 때의 기능을 수행할 뿐 아니라 

이 모드를 상태로 가지고 있는 스위치의 모드를 각각 반대 상태로 바꿔 넣어줍니다.

💡 모드의 전환이 예제처럼 ModeStateLight class의 toggle이나 ModeStateDark class의 toggle에 진행될지

아니면 ModeSwitch class의 onSwitch의 if else문으로 진행될지는 프로그램 특성에 따라 판단해서 선택하면 됩니다.

(3) 버튼을 눌러(modeSwitch) 상태를 전환(toggle)하게 되면 각각의 기능을 실행한 뒤

다른 상태(ModeStateDark 혹은 ModeStateLight)로 전환합니다.

 

다른 예시 더 보러가기

 

⭐️  참고한 곳  


얄팍한 코딩사전 : 객체지향 디자인패턴 1

https://www.youtube.com/watch?v=lJES5TQTTWE&t=1s

https://johngrib.github.io/wiki/pattern/state/

https://steady-coding.tistory.com/387

반응형