为了账号安全,请及时绑定邮箱和手机立即绑定

Python 中的状态模式

Python 中的状态模式

慕无忌1623718 2021-09-11 16:04:45
我在用 Python 实现状态设计模式时遇到了一些问题。我是 Python 的新手,并编写了一些代码来尝试回答提出给我的这个问题:为一个简单的 ATM 编写代码,允许用户插入他们的卡、输入他们的 PIN、请求现金和弹出卡。将以下对象模型用于显示状态模式使用的系统。您需要确定每个操作要更改为什么状态。请参阅下面的 UML 图以获取更多信息:下面是我的尝试...import reclass AtmState(object):    name = "ready"    allowed = []    def switch(self, state):        """ Switch to new state """        if state.name in self.allowed:#             print("Current {} => switched to new state {}.".format(self, state.name))            self.__class__=state# These print statements show how you switch between states.#         else:#             print("Current {} => switched to {} not possible.".format(self, state.name))    def getState(self):        print("The current state is {}".format(self.state))    def __str__(self):        return self.name    def __repr__(self):        return r"The ATM is in a {} state.".format(self.state)    def insertCard(self, card):        # Set messages for card format and inserted        wrong_format = "Please insert your card in the following format: XXXX-XXXX-XXXX-XXXX."        card_inserted = "Card Inserted: {}"        card_pattern='^([0-9]{4})(-?|\s)([0-9]{4})(-?|\s)([0-9]{4})(-?|\s)([0-9]{4})$'        pattern = re.compile(card_pattern)        if pattern.match(card) and str(self.state) in ["insert", "ready", "no card"]:            self.state.switch(HasCard)            print(card_inserted.format(card))            self.state.switch(HasPin)        elif pattern.match(card)==False and str(self.state) ["insert", "ready", "no card"]:            print(wrong_format)        elif str(self.state) in ["enter_pin", "withdraw"]:            print("Card already inserted")        elif str(self.state) in ["no card"]:            print("Error: No Card Inserted. Please insert card.")对我来说最大的困惑是如何使用类来实现它?我能够获得正确的逻辑,但我正在努力使用状态设计模式进行实现。任何指导将不胜感激。
查看完整描述

2 回答

?
噜噜哒

TA贡献1784条经验 获得超7个赞

这是您问题的简化版本的python3中的快速而肮脏的实现。


State 是一个抽象类,使用(Mickeal 描述的 abc 包)充当接口(派生类必须实现抽象方法)。实际状态接收请求并实现函数并执行状态转换这就是为什么我将 atm 对象作为参数方法传递


import abc

class State(object,metaclass = abc.ABCMeta):

    @abc.abstractmethod

    def eject(self, atm):

        raise NotImplementedError('')

    @abc.abstractmethod

    def insert(self, atm):

        raise NotImplementedError('')



class NoCard(State):

    def eject(self, atm):

        print('Error : no card')

    def insert(self, atm):

        print('ok')

        atm.state  = HasCard()


class HasCard(State):

    def eject(self, atm):

        print('ok')

        atm.state = NoCard()

    def insert(self, atm):

        print('Error : card already present')



class ATM:

    def __init__(self):

        self.state = NoCard()

    def insert(self):

        self.state.insert(self)

    def eject(self):

        self.state.eject(self)


if __name__ == "__main__":

    atm = ATM()

    atm.eject() # default state is no card error no card

    atm.insert() # ok state is has card

    atm.insert() # error  card already in

    atm.eject() # ok  state become no card

    atm.eject() # error no card



查看完整回答
反对 回复 2021-09-11
?
ITMISS

TA贡献1871条经验 获得超8个赞

Atm不应该从AtmState但从无(或从object,无所谓)继承。它应该只包含:state变量、change改变状态AtmState的方法以及调用当前同名方法的方法中的每个方法,并state带有一个名为例如atm包含调用Atm对象(上下文)的附加参数。

AtmState应该只包含没有实现的方法(并且没有变量),因为它是原始模式中的接口。对于 Python,您应该使其成为具有抽象方法的抽象类,请参阅模块abc如何做到这一点。

派生自的具体类AtmState现在应该实现这些方法。通常每个类只需要一两个方法,其余的应该只打印一个错误。例如,该NoCard.ejectCard()方法仅显示无法弹出不存在的卡的错误。

通过从方法之一调用atm.change()方法(atm是由Atm类添加的附加参数),可以在状态之间切换。


查看完整回答
反对 回复 2021-09-11
  • 2 回答
  • 0 关注
  • 229 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信