State mode - Python implementation

State mode

definition

State pattern: allows an object to change its behavior when its internal state changes, that is, different states correspond to different behaviors. Object appears to have modified its class.

In many cases, the behavior of an object depends on one or more dynamically changing attributes. Such properties are called States, and such objects are called stateful objects. The state is extracted from a series of defined values. When such an object interacts with external events, its internal state will change, so that the behavior of the system will also change.

scene

The behavior of an object depends on its state (for example, some attribute values). The change of state will lead to the change of behavior. There are a large number of conditional statements related to the object state in the code (if else), the appearance of these conditional statements will lead to poor code maintainability and flexibility, can not easily add and delete States, and lead to enhanced coupling between customer classes and class libraries.

State pattern is used to solve the state transformation of complex objects in the system and the encapsulation of behavior in different states. The state of an object is separated from the object and encapsulated into a special state class, so that the object state can change flexibly.

For example, in the Government OA office system, there are many states of an approval: it has not been handled; Processing; Under instruction; Under review; Completed and other statuses, and the operation of approval documents is different when the approval status is different. The state pattern can be used to describe the state transition of workflow objects (such as approvals) and its behavior in different states.

For another example, even if the elevator control logic is designed simply, the state is divided into open state, stop state and operation state, and the operation is divided into open state, close state, operation and stop. That process is also very complex. First, the door opening status cannot be opened, operated or stopped; The door cannot be closed in the stop state; The door cannot be opened, closed or operated in the operating state.

To implement if else one by one, first, the code is chaotic and difficult to maintain; Second, it is not easy to expand.

realization

Using state mode to realize elevator control logic

# Abstract class of state
class LiftState:
    def open(self):
        pass

    def close(self):
        pass

    def run(self):
        pass

    def stop(self):
        pass


# Specific state class
class OpenState(LiftState):
    def open(self):
        print("open: Elevator door is open, do not repeat operation")
        return self

    def close(self):
        print("open: The elevator door is about to close...")
        print("open: Elevator door closed")
        return CloseState()

    def run(self):
        print("open: Door opening status, no operation")
        return self

    def stop(self):
        print("open: Door opening status, no stopping")
        return self


class RunState(LiftState):
    def open(self):
        print("function: It is forbidden to open the door during operation")
        return self

    def close(self):
        print("function: It is forbidden to close the door during operation")
        return self

    def run(self):
        print("function: The elevator is already running. Please do not repeat the operation")
        return self

    def stop(self):
        print("function: The elevator is about to stop")
        print("function: The elevator has stopped")
        return StopState()


class StopState(LiftState):
    def open(self):
        print("stop it: The elevator door is about to open")
        print("stop it: The elevator door is open")
        return OpenState()

    def close(self):
        print("stop it: The elevator door is about to close")
        print("stop it: Elevator door closed")
        return CloseState()

    def run(self):
        print("stop it: The elevator is about to run")
        return RunState()

    def stop(self):
        print("stop it: The elevator has stopped. Please do not repeat the operation")
        return self


class CloseState(LiftState):
    def open(self):
        print("shut: The elevator door is about to open")
        print("shut: The elevator door is open")
        return OpenState()

    def close(self):
        print("shut: The elevator door is closed. Please do not repeat the operation")
        return self

    def run(self):
        print("shut: The elevator is about to run")
        return RunState()

    def stop(self):
        print("shut: It is forbidden to stop when the door is closed")
        return self


# Context class
class Context:
    lift_state = ""

    def get_state(self):
        return self.lift_state

    def set_state(self, lift_state):
        self.lift_state = lift_state

    def open(self):
        self.set_state(self.lift_state.open())

    def close(self):
        self.set_state(self.lift_state.close())

    def run(self):
        self.set_state(self.lift_state.run())

    def stop(self):
        self.set_state(self.lift_state.stop())


if __name__ == "__main__":
    ctx = Context()
    ctx.set_state(StopState())
    ctx.open()
    ctx.run()
    ctx.close()
    ctx.run()
    ctx.stop()
    ctx.get_state()

Pattern structure

Context (environment class): it is responsible for recording the status in the system and the transfer of scheduling status.

State (abstract state class): defines the behavior corresponding to the abstract state.

ConcreteState (concrete state class): defines the concrete behavior corresponding to the concrete state.

advantage

Encapsulated state transition rules, state transition codes can be managed centrally, rather than scattered in business methods.

Putting all the behaviors related to a state into one class, you only need to inject a different state object to make the environment object have different behaviors.

It allows state transition logic to be integrated with state objects instead of providing a huge conditional statement block, which can avoid using huge conditional statements to interweave business methods and state transition codes.

Multiple environment objects can share a state object, thus reducing the number of objects in the system.

shortcoming

It will increase the number of classes and objects in the system, resulting in an increase in the running cost of the system.

The structure and implementation are complex. Improper use will lead to confusion of program structure and code, and increase the difficulty of system design.

The support for the opening and closing principle is not very good. Adding a new state class requires modifying the source code responsible for state conversion, otherwise it cannot be converted to the new state; Moreover, modifying the behavior of a state class also requires modifying the source code of the corresponding class.

Keywords: Python Design Pattern

Added by astronaut on Sat, 25 Dec 2021 12:25:32 +0200