简化状态机 (Python)
Simplifying State Machines (Python)
我想知道为什么状态机完全使用中介“状态”class (between the Concrete States and the Context)。从下面的模型中,这可以用一个简单的变量来完成。
例如,这里有一个简化的“包含”式状态机,它满足相同的目标。与使用传统状态机模型相比,我使用这个模型失去了什么?
此外,附带问题,包含这些子 class 是因为它们是缩进的并且是父项 (Lift) class 的一部分。这种继承方式与取消缩进并将它们设置为这样的方式有什么区别:class FloorOne(Lift):
class Lift:
def __init__(self):
self.current_state = Lift.FloorOne(self)
def show_input_error(self):
print("Incorrect input")
class FloorOne:
def __init__(self, lift):
self.lift = lift
print("You are on Floor One")
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num == 2:
self.lift.current_state = Lift.FloorTwo(self.lift)
elif num == 3:
self.lift.current_state = Lift.FloorThree(self.lift)
else:
self.lift.show_input_error()
class FloorTwo:
def __init__(self, lift):
self.lift = lift
print("You are on Floor Two")
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num == 1:
self.lift.current_state = Lift.FloorOne(self.lift)
elif num == 3:
self.lift.current_state = Lift.FloorThree(self.lift)
else:
self.lift.show_input_error()
class FloorThree:
def __init__(self, lift):
self.lift = lift
print("You are on Floor Three")
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num == 1:
self.lift.current_state = Lift.FloorOne(self.lift)
elif num == 2:
self.lift.current_state = Lift.FloorTwo(self.lift)
else:
self.lift.show_input_error()
lift = Lift()
while True:
goto = input("What floor would you like to go to?")
lift.current_state.button_press(int(goto))
如果您将所有楼层 classes 定义为来自共同 class 状态的子 classes,您将获得:
从代码中可以看出,这是具体状态的公共接口。甚至你可以强制一个接口添加抽象方法,这些抽象方法必须在具体 classes 中被覆盖才能被实例化
您必须减少代码,因为您可以在状态 class 中定义一次对所有状态都相等的方法。例如 button_press
方法。
使代码更容易更改。
看这段代码:
class Lift:
def __init__(self):
self.current_state = Lift.FloorOne(self)
def show_input_error(self):
print("Incorrect input")
class State:
def __init__(self, lift):
self.lift = lift
print(f'You are on Floor {self.floor_name}')
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num != self.floor_num and num in [1,2,3]:
self.lift.current_state = [Lift.FloorOne,
Lift.FloorTwo,
Lift.FloorThree][num - 1](self.lift)
else:
self.lift.show_input_error()
class FloorOne(State):
floor_name = 'One'
floor_num = 1
class FloorTwo(State):
floor_name = 'Two'
floor_num = 2
class FloorThree(State):
floor_name = 'Three'
floor_num = 3
lift = Lift()
while True:
goto = input("What floor would you like to go to?")
lift.current_state.button_press(int(goto))
现在添加楼层更容易了。
如果需要,您可以覆盖子class 中的任何方法以获得不同的行为:
class BrokenLift(State):
def transition(self, num):
print('broken lift!')
我想知道为什么状态机完全使用中介“状态”class (between the Concrete States and the Context)。从下面的模型中,这可以用一个简单的变量来完成。
例如,这里有一个简化的“包含”式状态机,它满足相同的目标。与使用传统状态机模型相比,我使用这个模型失去了什么?
此外,附带问题,包含这些子 class 是因为它们是缩进的并且是父项 (Lift) class 的一部分。这种继承方式与取消缩进并将它们设置为这样的方式有什么区别:class FloorOne(Lift):
class Lift:
def __init__(self):
self.current_state = Lift.FloorOne(self)
def show_input_error(self):
print("Incorrect input")
class FloorOne:
def __init__(self, lift):
self.lift = lift
print("You are on Floor One")
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num == 2:
self.lift.current_state = Lift.FloorTwo(self.lift)
elif num == 3:
self.lift.current_state = Lift.FloorThree(self.lift)
else:
self.lift.show_input_error()
class FloorTwo:
def __init__(self, lift):
self.lift = lift
print("You are on Floor Two")
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num == 1:
self.lift.current_state = Lift.FloorOne(self.lift)
elif num == 3:
self.lift.current_state = Lift.FloorThree(self.lift)
else:
self.lift.show_input_error()
class FloorThree:
def __init__(self, lift):
self.lift = lift
print("You are on Floor Three")
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num == 1:
self.lift.current_state = Lift.FloorOne(self.lift)
elif num == 2:
self.lift.current_state = Lift.FloorTwo(self.lift)
else:
self.lift.show_input_error()
lift = Lift()
while True:
goto = input("What floor would you like to go to?")
lift.current_state.button_press(int(goto))
如果您将所有楼层 classes 定义为来自共同 class 状态的子 classes,您将获得:
从代码中可以看出,这是具体状态的公共接口。甚至你可以强制一个接口添加抽象方法,这些抽象方法必须在具体 classes 中被覆盖才能被实例化
您必须减少代码,因为您可以在状态 class 中定义一次对所有状态都相等的方法。例如
button_press
方法。使代码更容易更改。
看这段代码:
class Lift:
def __init__(self):
self.current_state = Lift.FloorOne(self)
def show_input_error(self):
print("Incorrect input")
class State:
def __init__(self, lift):
self.lift = lift
print(f'You are on Floor {self.floor_name}')
def button_press(self, num):
self.transition(num)
def transition(self, num):
if num != self.floor_num and num in [1,2,3]:
self.lift.current_state = [Lift.FloorOne,
Lift.FloorTwo,
Lift.FloorThree][num - 1](self.lift)
else:
self.lift.show_input_error()
class FloorOne(State):
floor_name = 'One'
floor_num = 1
class FloorTwo(State):
floor_name = 'Two'
floor_num = 2
class FloorThree(State):
floor_name = 'Three'
floor_num = 3
lift = Lift()
while True:
goto = input("What floor would you like to go to?")
lift.current_state.button_press(int(goto))
现在添加楼层更容易了。
如果需要,您可以覆盖子class 中的任何方法以获得不同的行为:
class BrokenLift(State):
def transition(self, num):
print('broken lift!')