State(状态) — 对象行为型模式
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用场景
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State 模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
UML 图
-
Context(环境)
- 定义客户感兴趣的接口。
- 维护一个 ConcreteState 子类的实例,这个实例定义为当前状态。
-
State(状态)
- 定义一个接口以封装与 Context 的一个特定状态相关的行为
-
ConcreteState subclasses(具体状态子类)
- 每一子类实现一个与 Context 的一个状态相关的行为
效果
- 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来
- 使得状态转换显式化:为不同的状态引入独立的对象使得转换变得更加明确。
- State 对象可被共享:如果 State 对象没有实例变量 — 它们表示的状态完全以它们的类型来编码 — 那么各 Context 对象可以共享一个 State 对象。当状态以这种方式被共享时,它们必然是没有内部状态而只有行为的轻量级对象。
一些考虑
- 谁定义状态转换:State 模式不指定哪个参与者定义状态转换准则。如果该准则是固定的,那么它们可在 Context 中完全实现。然而若让 State 子类自身指定它们的后继状态以及何时进行转换,通常更灵活,更何时。这需要 Context 增加一个接口,让 State 对象显式地设定 Context 的当前状态。用这种方法分散转换逻辑可以很容易地定义新的 State 子类来修改和扩展该逻辑。这样做的一个缺点是,一个 State 子类至少拥有一个其他子类的信息,这就在各子类之间产生了实现依赖。
- 基于表的另一种方法:可以基于表将记录状态转换。好处是可以通过更改数据而不是更改程序代码来改变状态转换的准则。坏处是1、 效率不高,2. 用统一的,表格形式表示转换逻辑使得转换准则不够明确且难以理解。3. 难以假如伴随状态转换的一些动作
实现
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'Andy'
"""
大话设计模式
设计模式——状态模式
状态模式(State Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
应用场景:当控制一个对象的状态转换的条件表达式过于复杂时,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化
(当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变他的行为)
"""
class State(object):
def __init__(self):
pass
def write_program(self, w):
pass
class Work(object):
def __init__(self):
self.hour = 9
self.curr = ForenoonState()
def set_state(self, s):
self.curr = s
def write_program(self):
self.curr.write_program(self)
class ForenoonState(State):
def write_program(self, w):
if w.hour < 12:
print "当前时间:%s点,"%w.hour,"精神百倍"
else:
w.set_state(AfternoonState())
w.write_program()
class AfternoonState(State):
def write_program(self, w):
if w.hour < 17:
print "当前时间:%s点,"%w.hour,"状态还行,继续努力"
else:
w.set_state(EveningState())
w.write_program()
class EveningState(State):
def write_program(self, w):
if w.hour < 21:
print "当前时间:%s点,"%w.hour,"加班呢,疲劳了"
else:
w.set_state(SleepState())
w.write_program()
class SleepState(State):
def write_program(self, w):
print "当前时间:%s点,"%w.hour,"不行了,睡着了"
client
if __name__=="__main__":
work = Work()
work.hour = 9
work.write_program()
work.hour = 15
work.write_program()
work.hour = 20
work.write_program()
work.hour = 22
work.write_program()
"""
output:
当前时间:9点, 精神百倍
当前时间:15点, 状态还行,继续努力
当前时间:20点, 加班呢,疲劳了
当前时间:22点, 不行了,睡着了
"""