7.13. State Machine

7.13.1. Rationale

  • EN: State Machine

  • PL: Maszyna Stanów

  • Type: class

7.13.2. Use Cases

  • StateMachine imposes a structure to automatically change the implementation from one object to the next

  • The current implementation represents the state that a system is in

  • System behaves differently from one state to the next

  • The code that moves the system from one state to the next

  • Each state can be run() to perform its behavior

  • You can pass it an input object so it can tell you what new state to move to based on that input

  • Each State object decides what other states it can move to, based on the input

  • Each State object has its own little State table

  • There is a single master state transition table for the whole system

7.13.3. Design

statemachine TrafficLight:
    Red -> Amber
    Amber (if previous == Red) -> Green
    Green -> Amber
    Amber (if previous == Green) -> Red


Red.wait = sleep(2)
Amber.wait = sleep(1)
Green.wait = sleep(2)

7.13.4. Implementation

from abc import ABCMeta, abstractmethod


class Tool(metaclass=ABCMeta):
    @abstractmethod
    def mouse_down(self) -> None:
        pass

    @abstractmethod
    def mouse_up(self) -> None:
        pass


class SelectionTool(Tool):
    def mouse_down(self) -> None:
        print('Selection icon')

    def mouse_up(self) -> None:
        print('Draw dashed rectangle')


class BrushTool(Tool):
    def mouse_down(self) -> None:
        print('Brush icon')

    def mouse_up(self) -> None:
        print('Draw line')


class Canvas:
    __current_tool: Tool

    def mouse_down(self) -> None:
        self.__current_tool.mouse_down()

    def mouse_up(self) -> None:
        self.__current_tool.mouse_up()

    def get_current_tool(self):
        return self.__current_tool

    def set_current_tool(self, newtool: Tool):
        self.__current_tool = newtool


if __name__ == '__main__':
    canvas = Canvas()
    canvas.set_current_tool(SelectionTool())

    canvas.mouse_down()
    # Selection icon

    canvas.mouse_up()
    # Draw dashed rectangle

7.13.5. Assignments