Страницы

Поиск по вопросам

вторник, 26 февраля 2019 г.

MVC для игры морской бой

Разделил логику от интерфейса на составляющие MVC
Model:
Класс Game в котором реализованы игроки, у каждого игрока есть поле, корабли и так далее
View:
2 объекта класса TField (визуальный компонент)
Controller:
Класс GameController, который должен связывать логику игры и ходы с визуальным представлением на форме.
Именно на контроллере стал задумываться, как связать их. Определить в классе GameController объекты классов модели и визуального представления? Но как их связать? Обработку нажатия на клетку в поле, отправку координат X и Y в класс Game и обратно получить ответ, обработав попадание/не попадание?
Я частично понял, как реализовать все это. У нас есть цепочка:
Представление -> Контроллер -> Модель
Представление вызывает клик и отправляет контроллеру событие о выстреле. Контроллер передает информацию об это модели на обработку. Но как сделать обновление Представления после изменений в Модели я так и не понял.
Я так понимаю, что нужно создать слушателя/-ей, которые будут вызываться из Модели при обновлении данных. Но это значит, что Модель должна содержать ссылку на Представление, что по сути перечит MVC, если Модель должна не знать о Представлении. Есть мысли?


Ответ

Смотрите. Вам нужен по идее event или Listener, или как там этот паттерн называется.
Суть такова.
Модель выставляет метод Subscribe(), в который можно передать callback, который будет вызван при изменении свойства. Представление знает о модели, и подписывается на её изменения. Таким образом, модель ничего не знает о представлении, но может дёрнуть это самое представление, когда что-то поменялось.
Пример на коленке:
class Model { public: typedef int Token;
Token subscribe(std::function callback) { max_token++; callbacks[max_token] = callback; return max_token; }
void unsubscribe(Token token) { callbacks.erase(token); }
private: std::map> callbacks; Token max_token = -1;
// это дёрнет все callback'и void notifyall() { for (auto& kv : callbacks) kv.second(); } };

class View { Model* model; Model::Token token;
//... View(Model* model) : model(model) { token = model->subscribe([this] { OnModelUpdate(); }); }
~View() { model->unsubscribe(token); } };

Комментариев нет:

Отправить комментарий