From: Firkraag on
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <list>

struct IObserver {
virtual ~IObserver(){}
virtual void update() = 0;
};

struct IObservable {
virtual ~IObservable(){}
virtual void registerObserver(IObserver& o) = 0;
virtual void removeObserver(IObserver& o) = 0;
virtual void notifyObservers() const = 0;
};

struct IModel : IObservable {
virtual ~IModel(){}
virtual void set(int n) = 0;
virtual void add(int n) = 0;
virtual void sub(int n) = 0;
virtual int get() const = 0;
};

class Model : public IModel {
public:
Model() : x(0) {}
Model(int n) : x(n) {}

virtual void set(int n) { x = n; notifyObservers(); }
virtual void add(int n) { set(get() + n); }
virtual void sub(int n) { set(get() - n); }
virtual int get() const { return x; }

virtual void registerObserver(IObserver& o)
{ container.push_back(&o); }
virtual void removeObserver(IObserver& o) { container.remove(&o); }
virtual void notifyObservers() const
{
for_each(container.begin(), container.end(),
std::mem_fun(&IObserver::update));
}

private:
int x;

typedef std::list<IObserver*> container_t;
container_t container;

};

struct IController;
class View : public IObserver {
public:
// num (just a displayed number of the view to indicate "different
views"
View(Model& mo, IController& ico, int num = 1) : m(&mo), ic(&ico),
n(num)
{
m->registerObserver(*this);
}

void displayView() { std::cout << "View " << n << " "; }
void hello() { std::cout << "Hello\n"; }
void bye() { std::cout << "Bye\n"; }
void promptMsg() { std::cout << "Enter a number: "; }

virtual void update()
{
displayView();
std::cout << m->get() << '\n';
}

private:
Model* m;
IController* ic;
int n;
};

struct IController {
virtual ~IController(){}
virtual void onOffSwitch() = 0;
virtual void set() = 0;
virtual void add() = 0;
virtual void sub() = 0;
};

class Controller : public IController {
public:
Controller(Model& mo) : m(&mo), v(0), isRunning(false)
{
v = new View(mo, *this);
}

virtual void onOffSwitch()
{
isRunning ^= true;
isRunning ? v->hello() : v->bye();
}

~Controller() { delete v; v = 0; }

virtual void set()
{
if(!isRunning) return;
v->promptMsg();
m->set(this->input());
}

void add()
{
if(!isRunning) return;
v->promptMsg();
m->add(this->input());
}

void sub()
{
if(!isRunning) return;
v->promptMsg();
m->sub(this->input());
}

private:
Model* m;
View* v;
bool isRunning;

int input() { int n; std::cin >> n; return n; }

Controller(Controller const&);
Controller& operator=(Controller const&);
};


int main()
{
Model m;
Controller c(m);
View view2(m, c, 2); // 2 is the displayed 2nd view's nr.

c.onOffSwitch();

c.set();
c.add();
c.sub();

c.onOffSwitch();
}

Am I doing it right? My question is also about the methods like
hello() and bye(). should they be a part of of the view? I was told
that view should be concerned only about "visualisation" of the model
and about itself. I wonder if hello() and bye() should belong to the
view or rather to the controller?

Thank you in advance.

From: Daniel T. on
Firkraag <firkraag07(a)tlen.pl> wrote:

[snipped code]

> Am I doing it right?

It's hard to tell, the solution is way more complicated than the problem
requires. :-) It seems to me that IObserverable and IModel serve no
purpose and can be removed.

> My question is also about the methods like hello() and bye().
> should they be a part of of the view? I was told that view should
> be concerned only about "visualisation" of the model and about
> itself. I wonder if hello() and bye() should belong to the view or
> rather to the controller?

I'd say hello() and bye() are in the right place. I think of it as the
View is in charge of output while the controller is in charge of input.

The hard part here is that MVC is specifically for mode-less systems,
but the console is model.