本文介绍了Python中的状态模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am having some issues wrapping my head around on implementing the state design pattern in Python.

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

I am new to Python and wrote some code to try and answer this question that was presented to me:

写一个简单的ATM的代码,该代码允许用户插入卡,输入PIN,索取现金并弹出卡.对于显示状态模式使用情况的系统,请使用以下对象模型.您将需要确定每次操作要更改为什么状态.

Write the code for a simple ATM that allows a user to insert their card, enter their PIN, request cash and eject card.Use the following object model for the system that shows the use of the State Pattern. You will need to figure what state to change to for each action.

有关更多信息,请参见下面的UML图:

ATM图

这是我在下面的尝试...

Here is my attempt below...

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


    def ejectCard(self):
        if str(self.state) in ["ready", "insert", "enter_pin", "withdraw"]:
            print("Card Ejected")
            self.state.switch(NoCard)
        else:
            print("Error: Card can't be Ejected - No Card Inserted")

    def requestCash(self, withdrawl):
        if str(self.state)=="withdraw":
            if self.balance >= withdrawl:
                self.balance-= withdrawl
                print("Withdrawing ${}.".format(withdrawl))
                if self.balance == 0:
                    print("Error: Out of Cash")
                else:
                    print("${} remaining in ATM.".format(self.balance))
            else:
                print("Error: Out of Cash")
        elif str(self.state)=="no card":
            print("Error: No Card inserted. Please insert your ATM card.")
        else:
            print("Error: Please enter pin.")

    def insertPin(self, pin):
        if str(self.state) == "enter_pin" and pin.isdigit() and len(pin)>=4:
            print("Pin Entered: {}".format(pin))
            self.state.switch(HasCash)
        elif str(self.state)== "no card":
            print("Error: No Card inserted. Please insert your ATM card.")
        else:
            print("Pin must be numeric and at least 4 digits.")

class HasCard(AtmState):
    name="insert"
    allowed=["no card", "enter_pin", "ready"]

class NoCard(AtmState):
    name="no card"
    allowed=["insert", "ready"]

class HasPin(AtmState):
    name="enter_pin"
    allowed=["no card", "withdraw", "insert"]

class HasCash(AtmState):
    name="withdraw"
    allowed=["no card"]

# This is known as the contect class. It does two main things:
# Defines the base state of the ATM...
# Defines a method to change the state of the ATM.
class Atm(AtmState):
    """A class representing an ATM"""

    def __init__(self, balance=2000):
        self.balance = balance
        # State of ATM - default is ready.
        self.state = NoCard()
        print("ATM has a balance of ${}".format(balance))

    def change(self, state):
        self.state.switch(state)

对我来说最大的困惑是如何使用类实现它?我能够使用正确的逻辑,但是我在使用状态设计模式进行实现时感到很挣扎.

The biggest point of confusion for me is how do I implement it using classes? I was able to get the correct logic in place but I am struggling with the implementation using the state design pattern.

任何指导将不胜感激.

Any guidance would be greatly appreciated.

推荐答案

在这里,这是您的问题的简单版本在python3中的一种快速而肮脏的实现.

Here is a quick and dirty implementation in python3 of a simplyfied version of your problem.

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

State is an abstract class using (abc package described by Mickeal) It acts as an interface (derived classes must implements abstract methods). Actual state receives the request and implements the function and performs the states transition this is why i pass the atm object as argument methods

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

这篇关于Python中的状态模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 00:35
查看更多