상세 컨텐츠

본문 제목

State 패턴 배워보기

Java

by techbard 2014. 1. 24. 19:59

본문

반응형

디자인 패턴 중 상태 패턴이라고 불리는 것으로 현재 상태 값에 따라서 각기 다른 동작을 보여야 하는 구현에 쓰인다. 특히 어떤 액션이 실행되고 나면 상태 또한 자동적으로 바뀌는 것을 구현한다.

 

먼저 상태 전이 다이어그램을 보고 설명을 해보자.

 

 

이와 같은 상태를 가지는 시스템을 구현한다고 가정하면,

 

1. 이 시스템은 총 3가지의 상태를 가진다. (S1, S2, S3)

2. 이러한 상태간의 전이를 발생시키는 이벤트는 총 5가지이며 A - E 까지이다.

3. S1 상태에서 S2 상태로의 전이는 A 이벤트에 의해 발생한다.

4. S3 상태에서 S1 상태로의 전이는 발생하지 않으며 기존 S3 상태를 그대로 유지한다.

 

이런 시스템을 구현해 보자.

 

먼저 A-E까지의 이벤트를 중심으로 구현할 것인가 아니면, 상태들의 전이를 중심으로 구현할 것인지 고민할 수 있다. 최초에는 매우 복잡하고 비객체지향적인 방식으로 구현을 해보았으나 동료의 조언에 의해 샘플 코드를 응용해서 (잉?) 작성하였다.

 

1. 먼저 S1, S2, S3 상태를 각각의 메소드로 보자. 구조적으로 객체지향적인 코드를 작성하기 위해서는 다형성 + 메소드 이름 트릭을 사용해야 한다. 인터페이스를 만든다.

 

 

2. 각 상태의 동작을 정의하는 클래스를 작성한다.

 

 

생각하는 방식은 다음과 같다. 위의 다이어그램을 봤을때

 

a. S1 상태에서 다시 S1 상태로 전이가 발생하면 일어나야 하는 동작은?

b. S1 상태에서 S2 상태로 전이가 발생하면 일어나야 하는 동작은?

c. S1 상태에서 S3 상태로 전이가 발생하면 일어나야 하는 동작은?

 

다이어그램 대로 코드 내용을 구현한다.

 

같은 방식으로 나머지 두 개의 클래스 S2.java, S3.java를 만든다.

 

 

 

 

3. 이제 상태의 저장을 담당하고 필요한 메소드를 호출하는 매니저 클래스를 만든다.

 

 

이 클래스에 대한 설명은 현재 할 수 없다. 테스트 클래스까지 나와야 한다.

 

4. 테스트 클래스를 작성하자.

 

 

이제 오묘한 객체지향 코드를 느껴보자.

 

a. 테스트 클래스에서 넘긴 S1 객체는 manager 객체변수에 저장된다.

b. 이때 StateManager 객체 내부의 멤버인 IState 타입의 state 변수에 S1 객체가 들어가게 된다.

c. 테스트 클래스에서 manager.s2(); 를 실행하면

d. state에는 현재 S1 클래스의 객체가 들어있으므로, 사실상 s1클래스의 객체 내부에 있는 s1()메소드가 호출된다. 현재 state에는 S1 객체가 들어있으므로 s1클래스.s1() 메소드로는 S1 상태에서 다시 S1 상태로 진입하는 시나리오를 구현한 것이된다. 따라서 "동일상태" 라는 스트링을 출력한다.

e. 그리고 나서 이 메소드에 있는 return this로 인해 StateManager 클래스의 멤버에는 자기 자신 객체가 또 들어가게 된다. 이로서 상태 전이가 일어났음에도 자기 자신 전이를 구현했다.

f. 이제 manager.s3(); 를 실행하면

g. StateManager 클래스의 s3() 메소드가 실행되고 이것은 다시 this.state = state.s3() 라인에 의해 S1 클래스 내의 s3() 메소드가 호출되고 "E 이벤트 발생" 출력 그리고 다시 state에는 S3 객체가 들어가게 된다.

 

이러한 방식으로 사전에 현재 상태에서 다른 상태로 전이할 때 일어나는 일들에 대한 정의를 먼저하고,

최초 생성자를 통해 Initial State를 저장해 두고 이후 다른 상태 전이를 호출하면 사전 정의된 대로 기존 상태를 유지할 것이냐, 새로운 상태를 리턴해서 저장하느냐가 실행되어 상태 전이 시스템을 구현하게 되었다.

 

필자는 최초에 이러한 테크닉을 이해하지 못하고 상태 클래스를 만들고 그 안에 switch case 문을 통해 상태 전환에 대한 로직을 구현하려고 했으나 전혀 객체지향 답지 않다는 말을 듣고는 샘플 코드를 보고 다시 작성하게 되었다. 훨씬 간단하고 구현하기도 쉽다. -_-

 

결과:

A 이벤트 발생
B 이벤트 발생
D 이벤트 발생
C 이벤트 발생
동일상태
E 이벤트 발생
가능하지 않음

 

StatePattern2.zip

 

반응형

관련글 더보기

댓글 영역