猿问

Python 中的状态模式

我在用 Python 实现状态设计模式时遇到了一些问题。

我是 Python 的新手,并编写了一些代码来尝试回答提出给我的这个问题:

为一个简单的 ATM 编写代码,允许用户插入他们的卡、输入他们的 PIN、请求现金和弹出卡。将以下对象模型用于显示状态模式使用的系统。您需要确定每个操作要更改为什么状态。

请参阅下面的 UML 图以获取更多信息:

下面是我的尝试...


import re


class 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.")


对我来说最大的困惑是如何使用类来实现它?我能够获得正确的逻辑,但我正在努力使用状态设计模式进行实现。


任何指导将不胜感激。


慕无忌1623718
浏览 230回答 2
2回答

噜噜哒

这是您问题的简化版本的python3中的快速而肮脏的实现。State 是一个抽象类,使用(Mickeal 描述的 abc 包)充当接口(派生类必须实现抽象方法)。实际状态接收请求并实现函数并执行状态转换这就是为什么我将 atm 对象作为参数方法传递import abcclass 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

ITMISS

Atm不应该从AtmState但从无(或从object,无所谓)继承。它应该只包含:state变量、change改变状态AtmState的方法以及调用当前同名方法的方法中的每个方法,并state带有一个名为例如atm包含调用Atm对象(上下文)的附加参数。AtmState应该只包含没有实现的方法(并且没有变量),因为它是原始模式中的接口。对于 Python,您应该使其成为具有抽象方法的抽象类,请参阅模块abc如何做到这一点。派生自的具体类AtmState现在应该实现这些方法。通常每个类只需要一两个方法,其余的应该只打印一个错误。例如,该NoCard.ejectCard()方法仅显示无法弹出不存在的卡的错误。通过从方法之一调用atm.change()方法(atm是由Atm类添加的附加参数),可以在状态之间切换。
随时随地看视频慕课网APP

相关分类

Python
我要回答