State pattern VS strategy pattern, what is the difference?

2019. 11. 10. 16:56Backend

운동을 하면서, 유투브로 디자인 패턴 관련 영상을 하나씩 보던 중 State pattern 에 대해 보는데, 이전에 보았던 strategy pattern 과 유사하다는 것을 알게 되었다.

그래서 한번 정리하고 가려 한다.

 

wikipedia 는 state pattern 에 대해 이렇게 이야기하고 있다 

 

 

The state pattern is a behavioral software design pattern that allows an object to alter its behavior when its internal state changes. This pattern is close to the concept of finite-state machines. The state pattern can be interpreted as a strategy pattern, which is able to switch a strategy through invocations of methods defined in the pattern's interface.

The state pattern is used in computer programming to encapsulate varying behavior for the same object, based on its internal state. This can be a cleaner way for an object to change its behavior at runtime without resorting to conditional statements and thus improve maintainability

 

State pattern 의 키워드는 '내부 상태의 변화에 따른 행동 변화' 'FSM' 인것 같다. 어떠한 상태의 변화를 조건문없이 해결할 수 있으며 새로운 상태가 추가되었을때, Client 코드의 변화 없이 상태를 추가하는 형태로 기능을 구현할 수 있다.

 

wiki 가 답을 주었다. state pattern 은 stretegy pattern 으로 해석될 수 있다고 이야기하고 있다. 

https://stackoverflow.com/questions/1658192/what-is-the-difference-between-strategy-design-pattern-and-state-design-pattern

 

What is the difference between Strategy design pattern and State design pattern?

What are the differences between the Strategy design pattern and the State design pattern? I was going through quite a few articles on the web but could not make out the difference clearly. Can so...

stackoverflow.com

그래도 GoF's Design pattern 에 두가지 패턴으로 나뉜 저자의 의도가 있을꺼라 생각 더 구글링해보았지만, 속 시원한 해설은 없다.

이런 저런 의견을 읽던 중 이런 생각이 들었다. '이러한 패턴으로 프로그래밍해라' 라는 정답이 있나? GoF는 그냥 이러한 형태로 해보면 어때의 제안을 하는 것일태고, 좋다고 생각하면 받아들이면 그만, State pattern 과 strategy 를 구분하여 사용하는 것이 무슨 의미가 있나? 라는 생각이 들었다.(패턴을 위한 프로그래밍인가? 프로그래밍을 이롭게 하기위한 패턴인가?) 

 

마지막으로 상태 패턴을 기억하기 위해 조금 더 정리하고 넘어가자.

State interface 가 있고 각 State 의 새부 명세가 있는 여러 개의 클래스들이 이를 구현한다. 

이 State 는 Context 에 deligated 되어 있으며, client 는 context 를 통해 상태를 변경한다.

 

일반적으로 Context 의 Constructor 혹은 setter method 를 이용하여 runtime 에 상태를 변경한다.

 

보다 상세한 이해를 위해

Wiki 의 예제를 보자.

interface State {
    void writeName(StateContext context, String name);
}

class LowerCaseState implements State {
    @Override
    public void writeName(StateContext context, String name) {
        System.out.println(name.toLowerCase());
        context.setState(new MultipleUpperCaseState());
    }
}

class MultipleUpperCaseState implements State {
    /* Counter local to this state */
    private int count = 0;

    @Override
    public void writeName(StateContext context, String name) {
        System.out.println(name.toUpperCase());
        /* Change state after StateMultipleUpperCase's writeName() gets invoked twice */
        if(++count > 1) {
            context.setState(new LowerCaseState());
        }
    }
}

State interface 를 정의하고 여러 State 를 구현했다.

class StateContext {
    private State state;
    
    public StateContext() {
        state = new LowerCaseState();
    }

    /**
     * Set the current state.
     * Normally only called by classes implementing the State interface.
     * @param newState the new state of this context
     */
    void setState(State newState) {
        state = newState;
    }

    public void writeName(String name) {
        state.writeName(this, name);
    }
}

Context Class 는 State  를 가지고 State 에 대한 수행을 정의한다.

public class StateDemo {
    public static void main(String[] args) {
        StateContext context = new StateContext();

        context.writeName("Monday");
        context.writeName("Tuesday");
        context.writeName("Wednesday");
        context.writeName("Thursday");
        context.writeName("Friday");
        context.writeName("Saturday");
        context.writeName("Sunday");
    }
}

Client 는 State 의 writeName 을 직접 호출하지 않는다 이는 state 메소드들은 일반적으로 package private 이어야하며 Context 를 통해서 State 내에 접근한다.

 monday
 TUESDAY
 WEDNESDAY
 thursday
 FRIDAY
 SATURDAY
 sunday

'Backend' 카테고리의 다른 글

Apache Avro  (0) 2019.11.13
Abstract Factory pattern  (0) 2019.11.12
Logger, Log4J? Slf4j?  (0) 2019.11.10
Retrofit, what is better?  (0) 2019.10.29
content length test  (0) 2019.09.30