什么是状态模式
允许一个对象在其内部状态发生改变时改变其行为,使这个对象看上去就像改变了它的类型一样。
状态即事物所处的某一种形态。状态模式是说一个对象在其内部状态发生改变时,其表现的行为和外在属性不一样,这个对象看上去就像改变了它的类型一样。因此状态模式又称为对象的行为模式。
状态模式设计思想
水有三种不同状态,冰、水、水蒸气。三种不同状态有完全不一样的外在特征:冰坚硬、水具有流动性,水蒸气,质轻。
状态模式的核心思想就是一个事物(对象)有多种状态,在不同的状态下所表现出来的行为和属性不一样。
代码:
"""
故事案例以水为例
"""
class Water:
"""水"""
def __init__(self, state):
self.__temp = 25
self.__state = state
def change_state(self, state):
if self.__state:
print('由', self.__state.get_name(), '变为', state.get_name())
else:
print('初始状态', state.get_name())
self.__state = state
def get_temp(self):
return self.__temp
def set_temp(self, temp):
self.__temp = temp
if self.__temp < 0:
self.change_state(SolidState('固态'))
elif self.__temp < 100:
self.change_state(LiquidState('液态'))
else:
self.change_state(GaseousState('气态'))
def rise_temp(self, step):
self.set_temp(self.__temp + step)
def reduce_temp(self, step):
self.set_temp(self.__temp - step)
def behavior(self):
self.__state.behavior(self)
class State:
def __init__(self, name):
self.__name = name
def get_name(self):
return self.__name
def behavior(self, water):
"""不同状态下的行为"""
pass
class SolidState(State):
"""固态"""
def __init__(self, name):
super().__init__(name)
def behavior(self, water):
print('我是的温度是' + str(water.get_temp()))
class LiquidState(State):
"""液态"""
def __init__(self, name):
super().__init__(name)
def behavior(self, water):
print('我是的温度是' + str(water.get_temp()))
class GaseousState(State):
"""气态"""
def __init__(self, name):
super().__init__(name)
def behavior(self, water):
print('我是的温度是' + str(water.get_temp()))
if __name__ == '__main__':
water = Water(LiquidState('液态'))
water.behavior()
water.set_temp(-5)
water.behavior()
water.set_temp(1000)
water.behavior()
代码架构
注意事项:1.水的状态有很多种,2.对于多种状态怎么判断3.类的状态的类只能有一种,不可固态1, 固态2,所以状态类要使用单例模式。
基本框架的实现
代码:
class Context:
"""状态模式的上下文环境"""
def __init__(self):
self.__states = []
self.__cur_state = None
# 状态改变依赖的属性,当这个变量由多个变量共同决定时可以将其单独定义成一个类
self.__state_info = 0
def add_state(self, state):
if state not in self.__states:
self.__states.append(state)
def get_state(self):
return self.__cur_state
def change_state(self, state):
if state is None:
return False
if self.__cur_state is None:
print('初始状态', state.get_name())
else:
print('由', self.__cur_state.get_name(), '转变', state.get_name())
self.__cur_state = state
self.add_state(state)
return True
def _set_state_info(self, state_info):
self.__state_info = state_info
for state in self.__states:
if state.is_match(state_info):
self.change_state(state)
def get_state_info(self):
return self.__state_info
class State:
"""状态的基类"""
def __init__(self, name):
self.__name = name
def get_name(self):
return self.__name
def is_match(self, state_info):
"状态的属性state_info是否存在当前的状态范围"
return False
class Water(Context):
def __init__(self):
super().__init__()
self.add_state(SolidState('固态'))
self.add_state(LiquidState('液态'))
self.add_state(GaseousState('气态'))
def set_temp(self, temp):
self._set_state_info(temp)
def get_temp(self):
return self.get_state_info()
def rise_temp(self, step):
self.set_temp(self.get_state_info() + step)
def reduce_temp(self, step):
self.set_temp(self.get_state_info() - step)
def behavior(self):
state = self.get_state()
if isinstance(state, State):
state.behavior(self)
# 单例模式装饰器
def singleton(cls, *args, **kwargs):
instance = {}
def __singleton(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return __singleton
@singleton
class SolidState(State):
"""固体"""
def __init__(self, name):
super().__init__(name)
def is_match(self, state_info):
return state_info < 0
def behavior(self, context):
print('我是固态温度是%s' % context.get_state_info())
@singleton
class LiquidState(State):
"""液态"""
def __init__(self, name):
super().__init__(name)
def is_match(self, state_info):
return state_info >=0 and state_info < 100
def behavior(self, context):
print('我是液体温度是%s' % context.get_state_info())
@singleton
class GaseousState(State):
"""气态"""
def __init__(self, name):
super().__init__(name)
def is_match(self, state_info):
return state_info > 100
def behavior(self, context):
print('我是气态温度是%s' % context.get_state_info())
if __name__ == '__main__':
water = Water()
water.behavior()
water.set_temp(-5)
water.behavior()
water.set_temp(1000)
water.behavior()
模型说明
设计要点
在实现状态模式的时候,实现的场景状态有时候会非常复杂,决定状态变化的因素也非常多,我们可以把决定状态变化的属性单独抽象成一个类StateInfo,这样判断状态属性是否符合当前的状态is_match时传入更多的信息。
每种状态应当只有唯一实例。
状态模型的优缺点
优点:
封装状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类中,对状态转换代码进行集中管理,而不是分散在一个个业务逻辑中。
将所有与某个状态有关的行为放到一个类中(称为状态类),使开发人员只专注与该状态下的逻辑开发。
允许状态转换逻辑与状态对象合为一体,使用时只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
缺点:
会增加系统类和对象的个数
状态模式的结构与现实都较为复杂,如果使用不当容易导致程序结构和代码混乱。
应用场景
一个对象的行为取决于它的状态,并且它在运行时可能会经常改变它的状态,从而改变它的行为。
一个操作中含有庞大的多分支条件语句,这些分支依赖与该对象的状态,并且每个分支的业务逻辑都非常的复杂,我们可以用状态模式来拆分不同的分支逻辑,使程序有更好的可读性和可维护性。