You will be fine

<디자인패턴입문> 16. State 패턴

by BFine
반응형

 

www.yes24.com/Product/Goods/2918928

 

Java 언어로 배우는 디자인 패턴 입문

이 책은 디자인 패턴의 입문서입니다. GoF가 정리한 23개의 디자인 패턴을 하나씩 다루면서 객체 지향을 잘 모르는 초보자도 이해하기 쉽도록 정리하고 있습니다. 단순한 이론이나 논리을 제시하

www.yes24.com

 

가. 무엇인가

 a. 상태를 클래스로!

  -  보통 프로그래밍할때 대상을 클래스로 표현하고 상태는 필드 행위는 메서드형태로 구성한다.  

  -  하지만 State(상태)패턴은 상태(사물의 모양이나 형편)을 클래스로 표현한다.

      => 클래스를 교체해 상태변화를 표현할 수 있고 새로운 상태 추가할때 무엇을 해야할지 분명해진다.

 

 b. 끝없는 if-else

  -  책에 있는 경비시스템에 대한 예제를 살펴보자. 틀린방법은 아니지만 메서드안에 if-else가 각각 들어간다.

  -  상태가 늘어날경우 모든 메서드에 if else 또한 반복되어져서 나오게 된다.

       => 만약 주간,야간이 아니라 한시간 단위라고 하면 각각 메서드에 24개의 분기처리를 반복처리해야한다.

class 경비시스템{

	금고사용(){
    	if(주간){
        	...
        }else if(야간){
        	...
        }
     }
     
     일지작성(){
     	if(주간){
        	...
        }else if(야간){
        	...
        }
     }
}

  -  State패턴을 적용하여 상태를 관점으로 하는 클래스를 구현하면 상태검사를 위한 if-else가 등장하지 않는다.

class 주간{

     금고사용(){
         ...
     }
     
     일지작성(){
         ...
     }
}

class 야간{

    금고사용(){
        ...
     }
     
     일지작성(){
        ...
     }
}

 

나. 만들어본 예제

사람의 감정을 클래스로 표현하는 예제

 a. State(상태)의 역할

  -  상태에 따라서 각각 동작하는 인터페이스를 작성한다.

public interface EmotionState {
    EmotionState behavior();
}

 b. ConcreteState(구체적인 상태)의 역할

  - 구체적인 상태를 각각 표현한다. 

  - 예제에서 화는 슬픔을 부른다는 것을 클래스를 변경함으로써 상태전환을 표현해보았다.

     => 현재상태를 나타내는 필드에 상태를 나타내는 클래스의 인스턴스를 대입하는 것이 상태전환이다.

public class AngryState implements EmotionState{
    @Override
    public EmotionState behavior() {
        System.out.println("버럭이 : 모니터를 때립니다.");
        System.out.println("버럭이 : 모니터 액정이 깨졌습니다.");
        return new SadState();
    }
}

public class HappyState implements EmotionState{
    @Override
    public EmotionState behavior() {
        System.out.println("행복이 : 웃고있습니다.");
        return this;
    }
}


public class SadState implements EmotionState{
    @Override
    public EmotionState behavior() {
        System.out.println("슬픔이 : 울고있습니다.");
        return this;
    }
}

 c. Context(상황, 전후관계, 문맥)의 역할

  -  현재의 상태를 나타내며 그 상태에 맞는 ConcreteState의 행위를 결정하는 역할을 한다.

      => 예제는 현재상태를 나타내는 역할만 하고 있다.

public class HumanContext {

    private EmotionState emotionState;

    public HumanContext(EmotionState emotionState) {
        this.emotionState = emotionState;
    }
    public void behavior(){
       emotionState = emotionState.behavior();
    }

    public void setEmotionState(EmotionState emotionState) {
        this.emotionState = emotionState;
    }
}

 d. Main

public class HumanContext {

    private EmotionState emotionState;

    public HumanContext(EmotionState emotionState) {
        this.emotionState = emotionState;
    }
    public void behavior(){
       emotionState = emotionState.behavior();
    }

    public void setEmotionState(EmotionState emotionState) {
        this.emotionState = emotionState;
    }
}

/**
"C:\Program Files\Java\jdk1.8.0_251\bin\java.exe"
행복이 : 웃고있습니다.
버럭이 : 모니터를 때립니다.
버럭이 : 모니터 액정이 깨졌습니다.
슬픔이 : 울고있습니다.
*/

 

다. 정리

 a. 분할해서 통치해라

  -  Divide and Conquer 은 복잡하고 규모가 큰 프로그램을 취급할 경우 방침이다.

      => 규모가 크고 복잡한 문제는 그대로 해결할려고 하면 안된다! 

  -  문제를 간단하게 해결할때까지 작게 나누어서 해결해야한다.

      => State 패턴에서는 상태를 클래스로 표현해서 문제를 분할한 것이다.

      => 내가 구현할  상태(ConcreteState) 클래스에만 집중할 수 있는 장점이 있다. 

 

 b. 상태전환은 누가 관리해야 하나?

  -  State 패턴을 사용할때 상태전환은 누가 관리해야 하는지 주의해야한다.

  -  예제는 상태전환을 상태클래스에서 하고 있다. 즉 상태에 의존한 동작으로 간주하고 있다.

       - 장점

            - 다른 상태로의 전환하는 것은 언제인가 하는 정보가 클래스내에 정리 되어있다.

       - 단점

            - 하나의 상태클래스의 역할이 다른상태클래스의 역할을 알아야하는 문제가 있다.

              => Sad 클래스를 삭제하면 Angry 클래스도 수정해야한다.

  -  다른 방법으로는 Context에게 모든 상태전환을 맡기는 것이다.

       - 장점

            - ConcreteState 역할의 독립성이 높아져 전체 예측이 좋아질 수 있다.

       - 단점

            - Context 역할이 모든 ConcreteState 역할을 알아햐 하는 단점이 있다.

      

c. State 패턴의 장단점

  - 장점

       - 새로운 상태를 추가할때 상태 클래스만 추가하기만 하면 된다. 

       - 어떤 메서드를 만들어야하는지가 명확해진다.

  - 단점

       - State 역할에 새로운 인터페이스를 추가하는 경우 모든 상태클래스에 구현해야한다.

상태패턴은 상태를 클래스로 나타내서 상태변경을 인스턴스 변경으로 표현하는 패턴이다.
반응형

블로그의 정보

57개월 BackEnd

BFine

활동하기