Смена MVC (MVP) триад в приложении
Подскажите пожалуйста подход к реализации подобного приложения. Если кратко, то необходимо переключаться между несколькими триадами MVP (MVC). В зависимости от выбранной в выпадающем списке модели, при нажатии на кнопки, должны появляться соответствующие представления, которые через нужного представителя связаны с моделью.
Если долго, то мне в голову пришел следующий способ. Далее много кода, но он простой.
Реализуем модели.
class IModel1(ABC):
@abstractmethod
def do_a(self, param):
pass
class ConcreteModel1(IModel1):
def do_a(self, param):
...
class IModel2(ABC):
@abstractmethod
def do_b(self, param):
pass
class ConcreteModel2(IModel2):
def do_b(self, param):
...
Реализуем представления. (View3 и View4 опущены).
class View(ABC):
@abstractmethod
def show(self):
pass
class IView1(View):
@abstractmethod
def get_a(self):
pass
class ConcreteView1(IView1):
def get_a(self):
...
class IView2(View):
@abstractmethod
def get_b(self):
pass
class ConcreteView2(IView2):
def get_b(self):
...
Реализуем представителей. (Presenter3 и Presenter4 опущены).
class Presenter(ABC):
@abstractmethod
def bind_view(self, view):
pass
@abstractmethod
def bind_model(self, model):
pass
class IPresenter1(Presenter):
@abstractmethod
def do_stuff_a(self):
pass
class ConcretePresenter1(IPresenter1):
def bind_view(self, view: IView1):
self._view = view
#Also connect self.do_work_a to View1 button or smth ...
def bind_model(self, model: IModel1):
self._model = model
def do_work_a(self):
self._model.do_a(self._view.get_a())
class IPresenter2(Presenter):
@abstractmethod
def do_stuff_b(self):
pass
class ConcretePresenter2(IPresenter2):
def bind_view(self, view: IView2):
self._view = view
#Also connect self.do_work_b to View2 button or smth ...
def bind_model(self, model: IModel2):
self._model = model
def do_work_b(self):
self._model.do_b(self._view.get_b())
Реализуем главное окно, в которое мы должны передать фабрику представлений, которая создает представления отображаемые по нажатию каждой кнопки.
class MainWindow(View):
def set_sub_views_factory(sub_views_fac):
self._btn1_view = sub_views_fac.create_btn1_view()
self._btn2_view = sub_views_fac.create_btn2_view()
def get_btn1_view(self):
return self._btn1_view
def get_btn2_view(self):
return self._btn2_view
#Button 1 callback
def show_btn1_view:
self._btn1_view.show()
#Button 2 callback
def show_btn2_view:
self._btn2_view.show()
def get_selected_model(self):
return 'Model name from drop down list'
Реализуем главного представителя, в который мы должны передать фабрику компонент приложения, которая в свою очередь возвращает фабрику представлений, фабрику представителей и модель.
При изменении модели в выпадающем списке, мы извлекаем из фабрики компонент нужные фабрики и обновляем все компоненты.
class MainPresenter:
def __init__(self, main_window, components_fac):
self._main_window = main_window
self._components_fac = components_fac
self._update_components()
# Callback for drop list (if it changes it's state)
def update_components(self):
model = self._main_window.get_selected_model()
sub_views_fac = self.components_fac.get_sub_views_fac(model)
self._main_window.set_sub_views_factory(sub_views_fac)
sub_presenters_fac = self.components_fac.get_sub_pres_fac(model)
model = self.components_fac.get_model(model)
self.bind_components(sub_presenters_fac, model)
def bind_components(self, sub_pres_fac, model):
self._btn1_presenter = sub_presenters_fac.get_btn1_pres()
self._btn1_presenter.bind_view(self._main_window.get_btn1_view())
self._btn1_presenter.bind_model(model)
self._btn2_presenter = sub_presenters_fac.get_btn2_pres()
self._btn2_presenter.bind_view(self._main_window.get_btn2_view())
self._btn2_presenter.bind_model(model)
Реализация фабрики компонент приложения.
class ComponentsFac:
models_views = {
'Model1': Model1SubViewsFac
'Model2': Model2SubViewsFac
}
models_presenters = {
'Model1': Model1SubPresFac
'Model2': Model2SubPresFac
}
models = {
'Model1': Model1
'Model2': Model2
}
def get_sub_views_fac(model):
return models_views[model]()
def get_sub_pres_fac(model):
return models_presenters[model]()
def get_model(model):
return models[model]()
Конкретные фабрики представлений и представителей, возвращают соответствующие (совместимые объекты).
# Concrete realization returns required views
class ISubViewsFac(ABC):
@abstractmethod
def get_btn1_view(self):
# Concrete realization for Model1 returns View1
# Concrete realization for Model2 returns View2
@abstractmethod
def get_btn2_view(self):
# Concrete realization for Model1 returns View3
# Concrete realization for Model2 returns View4
# Concrete realization returns required presenters
class ISubPresFac(ABC):
@abstractmethod
def get_btn1_pres(self):
# Concrete realization for Model1 returns Presenter1
# Concrete realization for Model2 returns Presenter2
@abstractmethod
def get_btn2_pres(self):
# Concrete realization for Model1 returns Presenter3
# Concrete realization for Model2 returns Presenter4
def main():
components_fac = ComponentsFac()
main_window = MainWindow()
main_presenter = MainPresenter(main_window, components_fac)
main_window.show()
Спасибо, если осилили это. У меня ощущение, что я нагородил тут фабрик фабрик фабрик... Может кому то приходилось реализовывать подобное?
