certain-design-patterns/state.py

81 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from abc import ABC, abstractmethod
# интерфейс состояния
class State(ABC):
@abstractmethod
def insert_coin(self): pass
@abstractmethod
def select_drink(self): pass
@abstractmethod
def dispense(self): pass
# состояние ожидания монеты
class WaitingForCoinState(State):
def __init__(self, vending_machine): self.vending_machine = vending_machine
def insert_coin(self):
print("Монета принята")
self.vending_machine.set_state(self.vending_machine.waiting_for_selection)
def select_drink(self):
print("Сначала вставьте монету")
def dispense(self):
print("Невозможно выдать напиток без оплаты")
# состояние "Нет товаров"
class OutOfStockState(State):
def __init__(self, vending_machine): self.vending_machine = vending_machine
def insert_coin(self): print("Нет товаров")
def select_drink(self): print("Нет товаров")
def dispense(self): print("Нет товаров")
# состояние "Ожидание выбора"
class WaitingForSelectionState(State):
def __init__(self, vending_machine): self.vending_machine = vending_machine
def insert_coin(self):
print("Монета уже вставлена")
def select_drink(self):
print("Напиток выбран")
self.vending_machine.set_state(self.vending_machine.dispensing)
def dispense(self):
print("Выберите напиток, прежде чем получить его")
# состояние "Выдача товара"
class DispensingState(State):
def __init__(self, vending_machine): self.vending_machine = vending_machine
def insert_coin(self): print("Идет выдача напитка")
def select_drink(self): print("Идет выдача напитка")
def dispense(self):
if self.vending_machine.stock > 0:
self.vending_machine.stock -= 1
print("Напиток выдан")
if self.vending_machine.stock == 0:
print("Товар закончился")
self.vending_machine.set_state(self.vending_machine.out_of_stock)
else:
self.vending_machine.set_state(self.vending_machine.waiting_for_coin)
else:
print("Товар закончился")
self.vending_machine.set_state(self.vending_machine.out_of_stock)
# контекст
class VendingMachine:
def __init__(self):
self.stock = 0
self.out_of_stock = OutOfStockState(self)
self.waiting_for_coin = WaitingForCoinState(self)
self.waiting_for_selection = WaitingForSelectionState(self)
self.dispensing = DispensingState(self)
self.state = self.out_of_stock
def set_state(self, state): self.state = state
def insert_coin(self): self.state.insert_coin()
def select_drink(self): self.state.select_drink()
def dispense(self): self.state.dispense()
def refill(self, amount):
self.stock += amount
print(f"Товар пополнен. Запас: {self.stock}")
if self.stock > 0:
self.set_state(self.waiting_for_coin)
vending_machine = VendingMachine()
vending_machine.refill(3)
vending_machine.insert_coin()
vending_machine.select_drink()
vending_machine.dispense()
vending_machine.select_drink()
vending_machine.insert_coin()
vending_machine.dispense()
vending_machine.dispense()
vending_machine.dispense()