GWT MVP с местами и мероприятиями - Где модель?

Я пытаюсь ознакомиться с шаблоном проектирования "Места и действия" для разработки GWT, и до сих пор я думаю, что он имеет большой потенциал. Мне особенно нравится, как после того, как вы начнете думать о своем приложении с точки зрения "Места", история браузера практически просто приземляется на ваши колени практически без особых усилий.

Однако меня беспокоит только одно: все статьи и примеры кода, которые я видел до сих пор, глядят на один (насколько мне известно, крупный) аспект: "M" часть "MVP", т.е. Модель!

В обычной MVP-архитектуре, насколько я понимаю, Presenter содержит ссылку на модель и отвечает за ее обновление в соответствии с событиями пользовательского интерфейса или, в частности, обновление пользовательского интерфейса в соответствии с изменениями модели.

Теперь, во всех статьях/образцах для "P & A", действия, похоже, занимают место Presenter, но в отличие от "нормальных" докладчиков, они отбрасываются и (повторно) создаются всякий раз, когда приходит новое место, поэтому они не могут быть теми, кто хранит состояние клиента, или он будет потерян каждый раз. Мероприятия дешевы для создания, поэтому это не так много хлопот, но я бы не хотел создавать модель сложного приложения снова и снова.

Все образцы достаточно просты и не имеют большого количества состояний и поэтому просто игнорируют аспект модели, но где бы фактическое сложное приложение сохраняло свое состояние?

Ответы

Ответ 1

Я думаю, что нашел свой собственный ответ. Основная проблема заключается в том, что все простые примеры кода делают действия "Ведущие", как в:

public class NavigationActivity extends AbstractActivity implements NavigationView.Presenter {
    private final ClientFactory clientFactory;
    private final NavigationPlace place;

    public NavigationActivity(ClientFactory clientFactory, NavigationPlace place) {
        this.clientFactory = clientFactory;
        this.place = place;
    }

    @Override
    public void start(AcceptsOneWidget panel, EventBus eventBus) {
        NavigationView navView = clientFactory.getNavigationView();
        navView.setSearchTerm(place.getSearchTerm());
        navView.setPresenter(this);
        panel.setWidget(navView);
    }

    @Override
    public void goTo(Place place) {
        clientFactory.getPlaceController().goTo(place);
    }
}

Теперь действия довольно короткоживущие, тогда как типичный Презентатор в "классическом" смысле имеет гораздо более продолжительный срок службы, чтобы поддерживать привязку между моделью и пользовательским интерфейсом. Так что я сделал, чтобы реализовать отдельный презентатор, используя стандартный шаблон дизайна MVP, и все действия выполняются примерно так:

public class NavigationActivity extends AbstractActivity {
    private final ClientFactory clientFactory;
    private final NavigationPlace place;

    public NavigationActivity(ClientFactory clientFactory, NavigationPlace place) {
        this.clientFactory = clientFactory;
        this.place = place;
    }

    @Override
    public void start(AcceptsOneWidget panel, EventBus eventBus) {
        NavigationPresenter presenter = clientFactory.getNavigationPresenter();
        presenter.setSearchTerm(place.getSearchTerm());
        presenter.go(panel);
    }
}

Итак, вместо того, чтобы Activity, получая представление и действуя как презентатор на нем, он извлекает фактический Presenter, просто информирует об изменении состояния клиента, вызванном Place, и сообщает ему, где отображать его информацию (т.е. вид). И тогда Presenter может свободно управлять представлением и моделью любым способом, который ему нравится - этот способ работает намного лучше (по крайней мере, с тем, что я имею в виду для приложения, над которым я работаю), чем примеры кода, которые я нашел так далеко.

Ответ 2

Вы правы, почти всегда ведущий - единственный парень, который держит модель и управляет ее жизнью. Модель из предыдущих версий GWT просто была DTO (и продолжает быть) POJO, которые создаются десериализатором GWT, когда методы RPC возвращаются или создаются Ведущими и заполняются данными пользовательского интерфейса UIHandlers, и отправляется на сервер.

Я приложил усилия, чтобы сохранить время жизни моделей, инкапсулированное в течение жизненного цикла Activities, и избегать хранения состояния вне действий. (Тем не менее, у меня есть одноэлементное глобальное состояние, которое поддерживается для использования в любом месте приложения.) Я думаю, что это то, что предполагают инженеры GWT MVP, - это имеет смысл, если, скажем, пользователь перешел от Place, поскольку модели, связанные с этим местом, также должны быть расположены (и собраны). Создавайте модели, заполняйте их внутри своих действий и делайте служебные вызовы для обновления сервера перед тем, как перейти (или вызван каким-то контролем на странице), и позволить им идти в ногу с деятельностью - это то, что я делал до настоящего времени.

Более крупный проект, в котором я участвовал, столкнулся с несколькими проблемами с памятью в памяти браузера, и все они были связаны с объектами, которые связаны с другим (не просмотренным в настоящее время) местом, находящимся в памяти. Трудно было отслеживать и удалять ссылки на эти объекты, а так как пользователь перешел от экрана - "почему мои старые экранные объекты все еще в памяти?" часто возникал вопрос, а затем исправлялся. Вот почему, заранее, я решил сохранить время жизни модели, инкапсулированное в течение жизненного цикла Activities в моем текущем проекте для домашних животных.

Если у вас есть модели, которые охватывают (которые заполняются/получают доступ) несколькими действиями (как в случае, если у вас есть боковые панели и виджеты мастера/контейнера), некоторые изменения дизайна могут быть в порядке, если у вас есть примеры, которые я буду попробуйте и помогите.