State Pattern

개념
- 상태를 클래스로 표현하는 패턴 , TCP연결 프로토콜

I. 의도  

    객체 자신의 내부 상태에 따라 행위를 변경하도록 한다. 객체가 클래스를 바꾸는 것처럼 보일 수 있다

    정의: 상태를 클래스로 표현하는 패턴 , TCP연결 프로토콜
          : 상태를 기반으로 한 행동을 캡슐화한 다음 위임을 통해서 필요한 행동을 선택 한다.

II. 활용

  • 객체의 상태에 따라 런타임시에 행위가 바뀌어야 할 때
  • 객체의 상태에 따라 수많은 조건 문장을 갖도록 오퍼레이션을 구현할 수 있는데, 어떤 경우는 동일한 조건 문장을 하나 이사으이 오퍼레이션에 중복 정의해야 할 수도 있다. 이때 객체의 상태를 별도의 객체로 정의함으로써 행위는 다른 객체와 상관없이 다양화 될 수 있다

III. 결과

  • 상태에 따른 행위를 국지화해 서로 다른 상태에 대한 행위를 별도의 객체로 관리한다 – 클래스 수가 많아질수 있다
  • 상태 전이 규칙을 명확하게 한다 – state 객체는 context 객체가 모순되 상태를 갖는 것을 막을 수 있다
  • 상태 객체는 공유할 수 있다

관련 패턴: State 객체를 만들고 공유하기 위해서는 Flyweight 패턴을 이용하면 되고, 인스턴스는 하나이므로 Singleton이다

 

 

적용전

적용후

// 3-speed ceiling fan state machine

// Not good: unwieldy "case" statement

 

class CeilingFanPullChain {

   private int m_current_state;

   public CeilingFanPullChain() {

      m_current_state = 0;

   }

public void pull() {

      if (m_current_state == 0) {

         m_current_state = 1;

         System.out.println( "   low speed" );

      } else if (m_current_state == 1) {

         m_current_state = 2;

         System.out.println( "   medium speed" );

      } else if (m_current_state == 2) {

         m_current_state = 3;

         System.out.println( "   high speed" );

      } else {

         m_current_state = 0;

         System.out.println( "   turning off" );

}  }  }

 

public class StateDemo {

   public static void main( String[] args ) {

      CeilingFanPullChain chain = new CeilingFanPullChain();

      while (true) {

         System.out.print( "Press " );

         get_line();

         chain.pull();

   }  }

static String get_line() {

      BufferedReader in = new BufferedReader(

            new InputStreamReader( System.in ));

      String line = null;

      try {

         line = in.readLine();

      } catch (IOException ex) {

         ex.printStackTrace();

      }

      return line;

}  }

<실행 결과>

// Press

//    low speed

// Press

//    medium speed

// Press

//    high speed

// Press

//    turning off

// Press

//    low speed

// Press

//    medium speed

// Press

//    high speed

// Press

//    turning off

 

// The CeilingFanPullChain class is now a wrapper

// that delegates to its m_current_state reference.

// Each clause from the "before" case statement is

// now captured in a State derived class.

 

class CeilingFanPullChain {

   private State m_current_state;

   public CeilingFanPullChain() {

      m_current_state = new Off(); }

   public void set_state( State s ) {

      m_current_state = s; }

   public void pull() {

      m_current_state.pull( this ); }

}

 

interface State {

   void pull( CeilingFanPullChain wrapper );

}

 

class Off implements State {

   public void pull( CeilingFanPullChain wrapper ) {

      wrapper.set_state( new Low() );

      System.out.println( "   low speed" );

}  }

 

class Low implements State {

   public void pull( CeilingFanPullChain wrapper ) {

      wrapper.set_state( new Medium() );

      System.out.println( "   medium speed" );

}  }

 

class Medium implements State {

   public void pull( CeilingFanPullChain wrapper ) {

      wrapper.set_state( new High() );

      System.out.println( "   high speed" );

}  }

 

class High implements State {

   public void pull( CeilingFanPullChain wrapper ) {

      wrapper.set_state( new Off() );

      System.out.println( "   turning off" );

}  }

 

public class StateDemo {

   public static void main( String[] args ) {

      CeilingFanPullChain chain =

                   new CeilingFanPullChain();

      while (true) {

         System.out.print( "Press " );

         get_line();

         chain.pull();

   }  }

   static String get_line() {

      BufferedReader in = new BufferedReader(

            new InputStreamReader( System.in ));

      String line = null;

      try {

         line = in.readLine();

      } catch (IOException ex) {

         ex.printStackTrace();

      }

      return line;

}  }

댓글