1.说明
在软件开发过程中,各种应用程序可能会根据不同的情况做出不同的处理。最直接的方案就是把所有的可能发生的情况都考虑到。然后使用条件语句if-elif-else
对不同情况的作出判断并进行处理。但是假如状态比较复杂,就会出现多个判断语句,判断语句中又包含这各种操作,这显然是不受欢迎的。状态模式的出现就是为了解决这种问题。
状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题,将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。
2.状态模式定义
状态模式:
允许一个对象在其内部状态改变时改变它的行为,即不同的状态对应了不同的行为。对象看起来似乎修改了它的类。
很多情况下,一个对象的行为取决于一个或者多个动态变化的属性。这样的属性叫做状态,这样的对象叫做有状态的对象。其状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之改变。
对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。
3.状态模式的结构
状态模式包含以下3个角色: Context(环境类) State(抽象状态类) ConcreteState(具体状态类)
实例:
电梯在我们周边随处可见,电梯的控制逻辑中心是由电梯控制器实现的。电梯的控制逻辑,即使简单点设计,把状态分成开门状态
,停止状态
和运行状态
,操作分成开门、关门、运行、停止
,那流程也是很复杂的。
首先,开门状态不能开门、运行、停止;停止状态不能关门,停止;运行状态不能开门、关门、运行。要用一个一个if…else…实现,首先代码混乱,不易维护;二是不易扩展。
但是可以看出的是,每个操作仅仅是一个操作,状态切换与操作是分离的,这也造成后来操作和状态“相互配合”的“手忙脚乱”。如果把状态抽象成一个类,每个状态为一个子类,每个状态实现什么操作,不实现什么操作,仅仅在这个类中具体实现就可以了。
class LiftState:
"""电梯状态,实现抽象的状态类"""
def open(self):
pass
def close(self):
pass
def run(self):
pass
def stop(self):
pass
# 实现各个具体的状态类
class OpenState(LiftState):
"""开门状态,具体的状态类"""
def open(self):
print("OPEN:The door is opened...")
return self
def close(self):
print("OPEN:The door start to close...")
print("OPEN:The door is closed")
return StopState()
def run(self):
print("OPEN:Run Forbidden.")
return self
def stop(self):
print("OPEN:Stop Forbidden.")
return self
class RunState(LiftState):
"""运行状态,具体的状态类"""
def open(self):
print("RUN:Open Forbidden.")
return self
def close(self):
print("RUN:Close Forbidden.")
return self
def run(self):
print("RUN:The lift is running...")
return self
def stop(self):
print("RUN:The lift start to stop...")
print("RUN:The lift stopped...")
return StopState()
class StopState(LiftState):
"""停止状态,具体的状态类"""
def open(self):
print("STOP:The door is opening...")
print("STOP:The door is opened...")
return OpenState()
def close(self):
print("STOP:Close Forbidden")
return self
def run(self):
print("STOP:The lift start to run...")
return RunState()
def stop(self):
print("STOP:The lift is stopped.")
return self
class Context:
"""为在业务中调度状态转移,还需要将上下文进行记录,需要一个上下文的类"""
lift_state = ""
def getState(self):
return self.lift_state
def setState(self, lift_state):
self.lift_state = lift_state
def open(self):
self.setState(self.lift_state.open())
def close(self):
self.setState(self.lift_state.close())
def run(self):
self.setState(self.lift_state.run())
def stop(self):
self.setState(self.lift_state.stop())
# 这样,在进行电梯的调度时,只需要调度Context就可以了。业务逻辑中如下
if __name__ == "__main__":
ctx = Context()
ctx.setState(StopState())
ctx.open()
ctx.run()
ctx.close()
ctx.run()
ctx.stop()
打印结果:
4.优缺点
4.1 优点
- 1.对象的行为是其状态的函数结果,并且行为在运行时根据状态而改变。
- 2.易于实现多态行为,并且易于添加状态来支持额外的行为。
- 3.提高聚合性,特定状态的行为被聚合到特定的状态子类中。通过只添加一个新的状态子类来添加行为是非常容易的。
因此,状态模式不仅改善了扩展应用程序行为时的灵活性,而且全面提高了代码的可维护性。
4.2 缺点
- 1.类爆炸:每个状态都需要在状态子类中定义,因此我们可能导致创建了太多功能较为单一的类。
- 2.结构与实现都较为复杂,如果使用不当将导致程序结构和代码混乱,增加系统设计的难度 。
- 3.对开闭原则的支持并不太好,增加新的状态类需要修改负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需要修改对应类的源代码。
5.状态模式适用环境
对象的行为依赖于它的状态(例如某些属性值),状态的改变将导致行为的变化 。
在代码中包含大量与对象状态有关的条件语句,这些条件语句的出现会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,并且导致客户类与类库之间的耦合增强。