Python设计模式中的状态模式你了解吗
短信预约 -IT技能 免费直播动态提醒
状态模式
状态模式,当对象的内部状态发生了改变的时候,允许对象执行不同的流程。
优点:
- 封装了状态转换规则。
- 枚举了可能的状态,在枚举状态之前需要确定状态的种类。
- 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
- 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
- 状态模式的使用必然会增加系统类和对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
- 状态模式对 “开闭原则” 并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
应用场景
- 行为随状态改变而改变的场景。
- 条件、分支语句的代替者。
代码示例
这是一个状态图,具有 “有 25 分钱”、“没有 25 分钱”、“售出糖果”、“糖果售罄” 这 4 个状态。同时也对应 4 个动作:“投入 25 分钱”,“退回 25 分钱”,“转动曲柄” 和 “发放糖果”。
class State:
# 定义state基类
def insert_quarter(self):
pass
def eject_quarter(self):
pass
def turn_crank(self):
pass
def dispense(self):
pass
class SoldOutState(State):
# 继承State 类
def __init__(self, gumball_machine):
self.gumball_machine = gumball_machine
def __str__(self):
return "sold_out"
def insert_quarter(self):
print("You can't insert a quarter, the machine is sold out")
def eject_quarter(self):
print("You can't eject, you haven't inserted a quarter yet")
def turn_crank(self):
print("You turned, but ther are no gumballs")
def dispense(self):
print("No gumball dispensed")
class SoldState(State):
# 继承State 类
def __init__(self, gumball_machine):
self.gumball_machine = gumball_machine
def __str__(self):
return "sold"
def insert_quarter(self):
print("Please wait, we're already giving you a gumball")
def eject_quarter(self):
print("Sorry, you already turned the crank")
def turn_crank(self):
print("Turning twice doesn't get you another gumball")
def dispense(self):
self.gumball_machine.release_ball()
if gumball_machine.count > 0:
self.gumball_machine.state = self.gumball_machine.no_quarter_state
else:
print("Oops, out of gumballs!")
self.gumball_machine.state = self.gumball_machine.soldout_state
class NoQuarterState(State):
# 继承State 类
def __init__(self, gumball_machine):
self.gumball_machine = gumball_machine
def __str__(self):
return "no_quarter"
def insert_quarter(self):
# 投币 并且改变状态
print("You inserted a quarter")
self.gumball_machine.state = self.gumball_machine.has_quarter_state
def eject_quarter(self):
print("You haven't insert a quarter")
def turn_crank(self):
print("You turned, but there's no quarter")
def dispense(self):
print("You need to pay first")
class HasQuarterState(State):
# 继承State 类
def __init__(self, gumball_machine):
self.gumball_machine = gumball_machine
def __str__(self):
return "has_quarter"
def insert_quarter(self):
print("You can't insert another quarter")
def eject_quarter(self):
print("Quarter returned")
self.gumball_machine.state = self.gumball_machine.no_quarter_state
def turn_crank(self):
print("You turned...")
self.gumball_machine.state = self.gumball_machine.sold_state
def dispense(self):
print("No gumball dispensed")
class GumballMachine:
def __init__(self, count=0):
self.count = count
# 找出所有状态,并创建实例变量来持有当前状态,然后定义状态的值
self.soldout_state = SoldOutState(self)
self.no_quarter_state = NoQuarterState(self)
self.has_quarter_state = HasQuarterState(self)
self.sold_state = SoldState(self)
if count > 0:
self.state = self.no_quarter_state
else:
self.state = self.soldout_state
def __str__(self):
return ">>> Gumball machine current state: %s" % self.state
def insert_quarter(self):
# 投入25分钱
self.state.insert_quarter()
def eject_quarter(self):
# 退回25分
self.state.eject_quarter()
# print("state", self.state, type(self.state))
def turn_crank(self):
# 转动曲柄
# print("state", self.state, type(self.state))
self.state.turn_crank()
def release_ball(self):
# 发放糖果
print("A gumball comes rolling out the slot...")
if self.count > 0:
self.count -= 1
if __name__ == "__main__":
# 以下是代码测试
gumball_machine = GumballMachine(5) # 装入5 个糖果
print(gumball_machine)
gumball_machine.insert_quarter() # 投入25分钱
gumball_machine.turn_crank() # 转动曲柄
print(gumball_machine)
gumball_machine.insert_quarter() #投入25分钱
gumball_machine.eject_quarter() # 退钱
gumball_machine.turn_crank() # 转动曲柄
print(gumball_machine)
gumball_machine.insert_quarter() # 投入25分钱
gumball_machine.turn_crank() # 转动曲柄
gumball_machine.insert_quarter() # 投入25分钱
gumball_machine.turn_crank() # 转动曲柄
gumball_machine.eject_quarter() # 退钱
print(gumball_machine)
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341