Learn the design pattern "State" in Python

I would like to learn GoF design patterns in Python.

■ State (state pattern)

The State pattern is a type of behavioral design pattern used in programming. This pattern is used to represent the state of an object. It's a clean way to work with objects that partially change their type at runtime.

UML class and sequence diagram W3sDesign_State_Design_Pattern_UML.jpg UML class diagram state.png (The above is quoted from Wikipedia)

□ Memorandum

In the State pattern, it seems that a thing called" state "is expressed by a class. It is possible to share the state-dependent behavior with the ConcreteState role here. However, when using the State pattern, it is important to note that ** who should manage the state transition **. (If you leave the state transition to the role of ConcreteState, the dependency between classes will be deepened.)

■ "State" sample program

Actually, I would like to run a sample program that utilizes the State pattern and check the following behavior. Here, imagine "Visualization of startup status by operating a personal computer" </ font>.

--When you start your computer, the operating status will be "running". --When you stop your computer, the operating status becomes "shutdown". --When you restart your computer, the operating status will change to "running".

In the sample program, specify ** first argument: first computer operation **, ** second argument: second computer operation **.

(Case 1) Start and stop the personal computer

The operating state first becomes "running" when the computer is started, and then becomes "shutdown" when the computer is stopped.

$ python Main.py start stop
###PC,[start]To do
***The computer is running
###The personal computer[running]Is now in operation

... sleep 5 second

###PC,[stop]To do
***The computer is stopped
###The operating status of the personal computer is[shutdown]became

(Case 2) Start the computer and restart it.

The operating state first becomes "running" when the computer is started, and then it becomes "running" again when the computer is restarted.

$ python Main.py start restart
###PC,[start]To do
***The computer is running
###The personal computer[running]Is now in operation

... sleep 5 second

###PC,[restart]To do
***The computer will start restarting
***The computer is running
###The operating status of the personal computer is[running]became

With the above, the sample program worked as expected.

■ Details of sample program

Similar code has been uploaded to the Git repository. https://github.com/ttsubo/study_of_design_pattern/tree/master/State

--Directory structure

.
├── Main.py
└── state
    ├── __init__.py
    ├── context.py
    └── state.py

(1) The role of State

The State role is meant to represent a state. Defines an interface that behaves differently for each state. In the sample program, the State class serves this role.

state/state.py


from abc import ABCMeta, abstractmethod

class State(metaclass=ABCMeta):
    @abstractmethod
    def handle(self):
        pass

(2) The role of ConcreteState

The ConcreteState role represents a specific individual state. Concretely implement the interface defined by the State role. In the sample program

--ConcreteStateBooting class --ConcreteStateRun class --ConcreteStateShutDown class --ConcreteStateRestart class

However, I will try this role.

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("***The computer is running")
        context.setState(ConcreteStateRun("running"))


class ConcreteStateRun(ConcreteState):
    def __init__(self, state):
        super(ConcreteStateRun, self).__init__(state)

    def handle(self, context):
        print("***The computer is in operation")


class ConcreteStateShutDown(ConcreteState):
    def __init__(self, state):
        super(ConcreteStateShutDown, self).__init__(state)

    def handle(self, context):
        print("***The computer is stopped")


class ConcreteStateRestart(ConcreteState):
    def __init__(self, state):
        super(ConcreteStateRestart, self).__init__(state)

    def handle(self, context):
        print("***The computer will start restarting")
        context.setState(ConcreteStateBooting("booting"))
        context.handle()

(3) The role of Context (state, context, context)

The Context role holds an object for the ConcreteState role that represents the current state. In the sample program, the Context class serves this role.

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) The role of Client

In the sample program, the startMain method serves this role.

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("###PC,[{0}]To do".format(initial_operation))
    obj.handle()
    print("###The personal computer[{0}]Is now in operation".format(obj.getState()))
    print("")

    print("... sleep 5 second")
    print("")
    time.sleep(5)

    obj.setState(setConcreteState(change_operation))
    print("###PC,[{0}]To do".format(change_operation))
    obj.handle()
    print("###The operating status of the personal computer is[{0}]became".format(obj.getState()))


if __name__ == "__main__":
    startMain(sys.argv[1], sys.argv[2])

■ Reference URL

-Design pattern in Python ~ Py design ~ / State pattern

Recommended Posts

Learn the design pattern "State" in Python
Learn the design pattern "Prototype" in Python
Learn the design pattern "Builder" in Python
Learn the design pattern "Flyweight" in Python
Learn the design pattern "Observer" in Python
Learn the design pattern "Memento" in Python
Learn the design pattern "Proxy" in Python
Learn the design pattern "Command" in Python
Learn the design pattern "Visitor" in Python
Learn the design pattern "Bridge" in Python
Learn the design pattern "Mediator" in Python
Learn the design pattern "Decorator" in Python
Learn the design pattern "Iterator" in Python
Learn the design pattern "Strategy" in Python
Learn the design pattern "Composite" in Python
Learn the design pattern "Adapter" in Python
Learn the design pattern "Abstract Factory" in Python
Learn the design pattern "Template Method" in Python
Learn the design pattern "Factory Method" in Python
Learn the design pattern "Chain of Responsibility" in Python
Learn the design pattern "Singleton" with Python
Learn the design pattern "Facade" with Python
Implement the Singleton pattern in Python
Visitor pattern in Python
State monad in python
Download the file in Python
Find the difference in Python
Design Patterns in Python: Introduction
Learn exploration in Python # 1 Full exploration
Python Design Pattern --Template method
Getting the arXiv API in Python
Python in the browser: Brython's recommendation
Save the binary file in Python
Hit the Sesami API in Python
Get the desktop path in Python
Get the script path in Python
In the python command python points to python3.8
Hit the web API in Python
I wrote the queue in Python
Calculate the previous month in Python
Examine the object's class in python
Get the desktop path in Python
Get the host name in Python
Access the Twitter API in Python
The first step in Python Matplotlib
I wrote the stack in Python
Custom state space model in Python
Master the weakref module in Python
Learn the basics of Python ① Beginners
Load the remote Python SDK in IntelliJ
Try using the Wunderlist API in Python
Check the behavior of destructor in Python
[Python Kivy] About changing the design theme
Try using the Kraken API in Python
Learn the basics while touching python Variables
Write the test in a python docstring
OR the List in Python (zip function)
GoF design pattern from the problem 2. Structure
Display Python 3 in the browser with MAMP
Tweet using the Twitter API in Python
Check if the URL exists in Python