Python 设计模式 — 行为型模式 — 状态模式

Posted 范桂飓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 设计模式 — 行为型模式 — 状态模式相关的知识,希望对你有一定的参考价值。

目录

文章目录

状态模式

状态模式,当对象的内部状态发生了改变的时候,允许对象执行不同的流程。

优点

  • 封装了状态转换规则。
  • 枚举了可能的状态,在枚举状态之前需要确定状态的种类。
  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点

  • 状态模式的使用必然会增加系统类和对象的个数。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 状态模式对 “开闭原则” 并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

应用场景

  • 行为随状态改变而改变的场景。
  • 条件、分支语句的代替者。

代码示例

这是一个状态图,具有 “有 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)

以上是关于Python 设计模式 — 行为型模式 — 状态模式的主要内容,如果未能解决你的问题,请参考以下文章

OOP设计模式Python实现--行为型模式之状态模式

Python 设计模式 — 行为型模式 — 备忘录模式

Python 设计模式 — 行为型模式 — 备忘录模式

Javascript设计模式

设计模式 行为型模式 -- 职责链模式(定义结构纯与不纯的职责链模具体案例)

手撸golang 行为型设计模式 状态模式