Помогите понять паттерн Model-View-Controller, как он выглядит в голом С++, а то в интернетах всё про php да java\C#
Как я его понимаю:
Допустим есть GUI который показывает данные и в котором есть кнопки\поля ввода чтобы данные менять.
Также есть какой-то код который делает какую-то полезную работу — использует эти данные и как-то реагирует на их изменение.
Допустим у нас есть один объект данных — класс Model
struct IModelReader
{
virtual A get_dataA() = 0;
virtual B get_dataB() = 0;
};
struct IModelWriter
{
virtual void set_dataA(A value) = 0;
virtual void set_dataB(B value) = 0;
};
struct IModel : IModelReader, IModelWriter
{
virtual void load() = 0;
virtual void save() = 0;
};
class Model : public IModel
{
public:
Model();
... тривиальная реализация get/set методов
};
и один объект GUI, у него будет класс UserInterface,
struct IView
{
virtual void updateAll() = 0;
};
class UserInterface : IView
{
public:
UserInterface(IModelReader& model, IController& controller);
virtual void updateAll()
{
outputForA.text = model.get_dataA().toString();
outputForB.text = model.get_dataB().toString();
}
private:
void onUserRequestChangeDataA(A newValue)
{
controller->setDataA(newValue);
}
void userWantReloadData() { controller->loadData(); }
void userWantCloseMe() { controller->saveData(); }
void seemsThatUserGoneAway() { controller->log("WARNING: user doesn't work"); }
...
}
и контроллер:
struct IController
{
virtual void setDataA(A newValue) = 0;
virtual void loadData() = 0;
virtual void saveData() = 0;
virtual void log(string s) = 0;
}
class Controller : public IController
{
public:
Controller(IModel& model, IView& view, ILog& log = ILog::getNullLogger());
virtual void setDataA(A newValue)
{
A oldA = model.get_dataA();
if(newValue == oldA)
return;
model.set_dataA(newValue);
view.updateAll();
log.log("A changed");
}
virtual void loadData()
{
model.load();
view.updateAll();
}
virtual void saveData()
{
model.save();
}
}
запускаем...
int main()
{
struct Holder
{
Holder() : m(), v(m, c), c(m, v) {}
Model m;
UserInterface v;
Controller c;
}
holder;
holder.v.run();
}
а кто же собственно будет делать полезную работу?
Controller и так перегружен методами.
Значит надо делать еще один класс, например Worker, который тоже должен читать\писать данные, и знать об их изменении.
Для уведомления об изменении есть IView::updateAll(), значит можно написать
struct ComplexView : IView
{
virtual void updateAll() { for each(IView* v in views) v->updateAll(); }
list<IView*> views;
};
Впрочем у Worker'а всеравно будут методы которых нет у GUI и наоборот, так что и UserInterface, и Worker надо передавать Controller'у
class Worker : IView
{
void beginCalculateValueOfA(function<void(A)> handler) { ... }
};
void Controller::updateA()
{
worker.beginCalculateValueOfA([this](A a){ model.set_dataA(a); allViews.updateAll(); });
}
так как оно, MVC, на самом деле выглядит?
Здравствуйте, Abyx, Вы писали:
A>Помогите понять паттерн Model-View-Controller, как он выглядит в голом С++, а то в интернетах всё про php да java\C#
A>Как я его понимаю:
A>Допустим есть GUI который показывает данные и в котором есть кнопки\поля ввода чтобы данные менять.
A>Также есть какой-то код который делает какую-то полезную работу — использует эти данные и как-то реагирует на их изменение.
A>Допустим у нас есть один объект данных — класс Model
A>A>struct IModelReader
A>{
A> virtual A get_dataA() = 0;
A> virtual B get_dataB() = 0;
A>};
A>struct IModelWriter
A>{
A> virtual void set_dataA(A value) = 0;
A> virtual void set_dataB(B value) = 0;
A>};
A>struct IModel : IModelReader, IModelWriter
A>{
A> virtual void load() = 0;
A> virtual void save() = 0;
A>};
A>class Model : public IModel
A>{
A>public:
A> Model();
A> ... тривиальная реализация get/set методов
A>};
A>
A>запускаем...
A>а кто же собственно будет делать полезную работу?
A>Controller и так перегружен методами.
A>Значит надо делать еще один класс, например Worker, который тоже должен читать\писать данные, и знать об их изменении.
А модель-то у тебя — пустенькая
Здравствуйте, Abyx, Вы писали:
A>Помогите понять паттерн Model-View-Controller, как он выглядит в голом С++, а то в интернетах всё про php да java\C#
[skip]
A>а кто же собственно будет делать полезную работу?
Model как раз и делает. Правда, присоединюсь к Лаптеву — у тебя не понятно, в чём именно заключается полезная работа.
A>Controller и так перегружен методами.
A>Значит надо делать еще один класс, например Worker, который тоже должен читать\писать данные, и знать об их изменении.
А Model-то тебе на что? Плюс к тому, группа классов Controller-слоя в структуре MVC запросто может быть "аццки" огромной.
A>
A>так как оно, MVC, на самом деле выглядит?
Как захочешь, так и будет выглядеть — это же не требование, а свод рекомендаций. Посмотри для примера MFC — там как раз MVC реализован. Собственно, здесь важно только не упускать из виду соответствие между фактическим кодом и ролью, обозначаемой соответствующей буквой в названии паттерна: модель (M-model, нечто полезное), представление (V-view), связующее звено (C-controller). Что именно будет навалено в каждый из этих слоёв — решается в каждой программе по-своему. Притом, да, конкретное воплощение Model может являться неким своеобразным отображением какого-то полезного процесса и у этого процесса этих самых Model может быть много.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Как захочешь, так и будет выглядеть — это же не требование, а свод рекомендаций. Посмотри для примера MFC — там как раз MVC реализован.
И никто тогда не знал, что это великий и ужасный паттерн
Здравствуйте, Pavel Dvorkin, Вы писали:
ГВ>>Как захочешь, так и будет выглядеть — это же не требование, а свод рекомендаций. Посмотри для примера MFC — там как раз MVC реализован.
PD>И никто тогда не знал, что это великий и ужасный паттерн
Ага, это называлось "воплощением архитектуры SAA/CUA", если я ничего не путаю.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>>Как захочешь, так и будет выглядеть — это же не требование, а свод рекомендаций. Посмотри для примера MFC — там как раз MVC реализован.
PD>И никто тогда не знал, что это великий и ужасный паттерн
если б это архитектурное решение больше никому б не понадобилось — никто бы и не узнал
Здравствуйте, Denys V., Вы писали:
DV>если б это архитектурное решение больше никому б не понадобилось — никто бы и не узнал
Это "архитектурное решение" — суть простейшее и наивное первое приближение. Декомпозиция простая до безобразия: полезный код — отображение — связующее звено промеж них. Потому его никто и не может толком понять — понимать-то нечего.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!