[C++] объясните MVC
От: Abyx Россия  
Дата: 20.05.11 23:38
Оценка: 1 (1)
Помогите понять паттерн 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, на самом деле выглядит?
In Zen We Trust
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.