Реализация паттерна MVC в Python
Сложности в понимании паттерна MVC и его практической реализации на Python. Пытаюсь ради интереса создать консольную ATM, где пользователь условно создает себе счета и карты, привязанные к ним, а заодно и закрепить практику MVC паттерна.
controllers.py
from abc import ABC, abstractmethod, abstractproperty, abstractclassmethod, abstractstaticmethod
from models import ATMModel
from views import ABC_ATMView
class ABC_ATMController(ABC):
pass
class ATMController(ABC_ATMController):
model: ATMModel
view: ABC_ATMView
def __init__(self, model: ATMModel, view: ABC_ATMView):
self.model = model
self.view = view
def entry_point(self):
menu = self.view.show_entry_point()
if menu.chosen == "1":
form = self.view.show_sign_in_form()
elif menu.chosen == "2":
form = self.view.show_sign_up_form()
views.py
from abc import ABC, abstractmethod, abstractproperty, abstractclassmethod, abstractstaticmethod
from os import system, name
from mixin import SignInDTO, SignUpDTO, MenuChoice
class ABC_ATMView(ABC):
@abstractmethod
def show_entry_point(self) -> MenuChoice: ...
@abstractmethod
def show_sign_in_form(self) -> SignInDTO: ...
@abstractmethod
def show_sign_up_form(self) -> SignUpDTO: ...
class ATMViewTerminal(ABC_ATMView):
@staticmethod
def get_input(input_title: str = None, allowed_values: list = None):
value = input(f"{input_title + ': ' if input_title else '>>> '}")
if allowed_values:
while value not in allowed_values:
value = input(f"Неверное значение: ")
return value
@staticmethod
def clear():
if name == 'nt':
_ = system('cls')
else:
_ = system('clear')
@staticmethod
def draw_header(custom_title: str = None):
print(f"{'='*15} {'ATM Bank' if not custom_title else custom_title} {'='*15}")
@staticmethod
def draw_option(n: int, option_title: str):
return print(f"{n} > {option_title.capitalize()}")
def show_entry_point(self):
self.draw_header()
self.draw_option(1, option_title="У меня есть аккаунт")
self.draw_option(2, option_title="У меня нет аккаунта")
choice = self.get_input(allowed_values=["1", "2"])
self.clear()
return MenuChoice(choices=["1", "2"], chosen=choice)
def show_sign_in_form(self) -> SignInDTO:
self.draw_header("Вход")
login = self.get_input("Логин")
password = self.get_input("Пароль")
self.clear()
return SignInDTO(login, hash(password))
def show_sign_up_form(self) -> SignUpDTO:
self.draw_header("Регистрация")
login = self.get_input("Логин")
password, password_c = "1", "2"
while password != password_c:
password = self.get_input("Пароль")
password_c = self.get_input("Подтверждение пароля")
self.clear()
return SignUpDTO(login, hash(password), hash(password_c))
Проблема заключается в том, что я не могу понять кто, а точнее какой объект должен переключать view в зависимости от input'a ? Сейчас это делает ATMController в методе entry_point(), где в зависимости от input'a переключает формы, то есть форму входа и форму регистрации. Однако это делает ATMController зависимым от конкретной реализации View, а именно TerminalView, чего хочется избежать, но не знаю как...