파이썬에서 디자인 패턴 "State"를 배우십시오.

GoF의 디자인 패턴을 Python으로 학습하고 싶습니다.

■ State(상태 패턴)



State 패턴은 프로그래밍에 사용되는 동작에 관한 디자인 패턴의 일종이다. 이 패턴은 객체의 상태를 나타내는 데 사용됩니다. 런타임에서 유형을 부분적으로 변경하는 객체를 처리하는 깨끗한 수단입니다.

UML class and sequence diagram





UML 클래스 diagram




(이상 위키피디아(Wikipedia)에서 인용)

□ 비망록


State 패턴에서는, 「상태」라고 하는 물건을 클래스로 표현한다고 합니다.
상태에 의존하는 행동을 여기의 ConcreteState 역에 분담시키는 것이 가능하게 됩니다.
다만, State 패턴을 사용할 경우, 상태 천이를 누가 관리해야 하는가 하는 점에는 주의가 필요합니다.
(상태 천이를 ConcreteState 역할에 맡겨 버리면 클래스간의 의존관계를 깊게 해 버립니다.)

■ "State" 샘플 프로그램



실제로 State 패턴을 활용한 샘플 프로그램을 움직여서 다음과 같은 동작의 모습을 확인하고 싶습니다. 여기에서는, 「PC 조작에 의한 기동 상태의 가시화」를 이미지 해 주세요.
  • PC를 기동하면, 동작 상태는, 「running」이 된다
  • 컴퓨터를 멈추면 작동 상태가 "shutdown"이됩니다
  • 컴퓨터를 재시작하면 동작 상태가 "running"이 됩니다

  • 샘플 프로그램에서는 첫 번째 인수 : 첫 번째 PC 조작, 두 번째 인수 : 두 번째 PC 조작을 지정합니다.

    (사례 1) 컴퓨터를 시작하고 중지



    동작 상태는, 최초, PC에 기동에 의해, "running"이 되어, 그 후, PC의 정지에 의해, "shutdown"이 됩니다.
    $ python Main.py start stop
    ### パソコンを、[start]します
    *** パソコンは、起動中です
    ### パソコンは、[running]の動作状態になりました
    
    ... sleep 5 second
    
    ### パソコンを、[stop]します
    *** パソコンは、停止しています
    ### パソコンの動作状態は、[shutdown]になりました
    

    (사례 2) 컴퓨터를 시작하고 다시 시작합니다.



    동작 상태는, 최초, PC에 기동에 의해, "running"이 되고, 그 후, PC의 재기동에 의해, 다시, "running"이 됩니다.
    $ python Main.py start restart
    ### パソコンを、[start]します
    *** パソコンは、起動中です
    ### パソコンは、[running]の動作状態になりました
    
    ... sleep 5 second
    
    ### パソコンを、[restart]します
    *** パソコンは、再起動をはじめます
    *** パソコンは、起動中です
    ### パソコンの動作状態は、[running]になりました
    

    이상으로, 예상대로, 샘플리 프로그램이 동작했습니다.

    ■ 샘플 프로그램에 대해 자세히 알아보기



    Git 저장소에도 비슷한 코드가 있습니다.
    htps : // 기주 b. 코 m / 싹 / s dy_ 오 f_로 해 응 _ 파테 r
  • 디렉토리 구성
  • .
    ├── Main.py
    └── state
        ├── __init__.py
        ├── context.py
        └── state.py
    

    (1) State(상태)의 역할


    State 역할은 상태를 나타내는 것입니다. 상태마다 다른 행동을 하는 인터페이스를 정합니다.
    샘플 프로그램에서는, State 클래스가, 이 역할을 노력합니다.

    state/state.py
    from abc import ABCMeta, abstractmethod
    
    class State(metaclass=ABCMeta):
        @abstractmethod
        def handle(self):
            pass
    

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


    ConcreteState 역은 구체적인 개개의 상태를 표현하는 것입니다.State 역할로 정해진 인터페이스를 구체적으로 구현합니다.
    샘플 프로그램에서는
  • ConcreteStateBooting 클래스
  • ConcreteStateRun 클래스
  • ConcreteStateShutDown 클래스
  • ConcreteStateRestart 클래스

  • 하지만이 역할을 노력합니다.

    state/state.py
    class ConcreteState(State):
        def __init__(self, state):
            self.state = state
    
        def getConcreateState(self):
            return self.state
    
    
    class ConcreteStateBooting(ConcreteState):
        def __init__(self, state):
            super(ConcreteStateBooting, self).__init__(state)
    
        def handle(self, context):
            print("*** パソコンは、起動中です")
            context.setState(ConcreteStateRun("running"))
    
    
    class ConcreteStateRun(ConcreteState):
        def __init__(self, state):
            super(ConcreteStateRun, self).__init__(state)
    
        def handle(self, context):
            print("*** パソコンは、動作中です")
    
    
    class ConcreteStateShutDown(ConcreteState):
        def __init__(self, state):
            super(ConcreteStateShutDown, self).__init__(state)
    
        def handle(self, context):
            print("*** パソコンは、停止しています")
    
    
    class ConcreteStateRestart(ConcreteState):
        def __init__(self, state):
            super(ConcreteStateRestart, self).__init__(state)
    
        def handle(self, context):
            print("*** パソコンは、再起動をはじめます")
            context.setState(ConcreteStateBooting("booting"))
            context.handle()
    

    (3) Context (상태, 전후 관계, 문맥)의 역할


    Context 역할은 현재 상태를 나타내는 ConcreteState 역할의 개체를 보유합니다.
    샘플 프로그램에서는, Context 클래스가, 이 역할을 노력합니다.

    state/context.py
    class Context(object):
        def __init__(self, stateObj):
            self.state = stateObj
    
        def setState(self, obj):
            self.state = obj
    
        def handle(self):
            self.state.handle(self)
    
        def getState(self):
            return self.state.getConcreateState()
    

    (4) Client(의뢰인)의 역할



    샘플 프로그램에서는, startMain 메소드가, 이 역할을 노력합니다.

    Main.py
    import sys
    import time
    from state.context import Context
    from state.state import ConcreteStateBooting, ConcreteStateRun, ConcreteStateShutDown, ConcreteStateRestart
    
    
    def setConcreteState(operation):
        if operation == "start":
            return ConcreteStateBooting("booting")
        elif operation == "stop":
            return ConcreteStateShutDown("shutdown")
        elif operation == "restart":
            return ConcreteStateRestart("restart")
    
    def startMain(initial_operation, change_operation):
        obj = Context(setConcreteState(initial_operation))
        print("### パソコンを、[{0}]します".format(initial_operation))
        obj.handle()
        print("### パソコンは、[{0}]の動作状態になりました".format(obj.getState()))
        print("")
    
        print("... sleep 5 second")
        print("")
        time.sleep(5)
    
        obj.setState(setConcreteState(change_operation))
        print("### パソコンを、[{0}]します".format(change_operation))
        obj.handle()
        print("### パソコンの動作状態は、[{0}]になりました".format(obj.getState()))
    
    
    if __name__ == "__main__":
        startMain(sys.argv[1], sys.argv[2])
    

    ■ 참고 URL


  • Python의 디자인 패턴 ~ Py 디자이너 ~ / State 패턴
  • State Design Pattern In Python
  • 좋은 웹페이지 즐겨찾기