MVC是一种复合模式,结合了观察者,策略模式和组合模式。

要点:
1.模型使用观察者模式,以便观察者更新,同时保持两者之间解耦。
2.控制器是视图的策略,视图可以使用不同的控制器实现,得到不同的行为。
3.视图使用组合模式实现用户界面,用户界面通常组合了嵌套的组件,像面板,框架和按钮。
4.这些模式携手合作,把MVC模型的三层解耦,这样可以保持设计干净又有弹性。
5.适配器模式用来将新的模型适配成已有的视图和控制器


[img]http://dl.iteye.com/upload/attachment/522476/83a2a81c-040d-3019-b605-7b904f949673.png[/img]

model.h

#ifndef MODEL_H
#define MODEL_H
#include<list>
#include"NumObserver.h"
using namespace std;

class Model{
private:
    int number;
    list<NumObserver*> lst;
public:
    virtual int getNum()const=0;
    virtual void setNum(int num)=0;
    virtual void registerObserver(NumObserver* o)=0;
    virtual void removeObserver(NumObserver* o)=0;
    virtual void notifyObserver()=0;
};

class NumModel:public Model{
private:
    int number;
    list<NumObserver*> lst;
public:
    virtual int getNum()const{
        return number;
    }
    virtual void setNum(int num){
        number = num;
    }
    virtual void registerObserver(NumObserver* o){
        lst.push_back(o);
    }
    virtual void removeObserver(NumObserver* o){
        lst.remove(o);
    }
    virtual void notifyObserver(){
        list<NumObserver*>::iterator iter=lst.begin();
        while(iter!=lst.end()){
            (*iter)->update(number);
            ++iter;
        }
    }
};

#endif // MODEL_H



NumObserver.h


#ifndef NUMOBSERVER_H
#define NUMOBSERVER_H

class NumObserver{
public:
    virtual void update(int num)=0;
    virtual int getNum()const=0;
};

class Num:public NumObserver{
private:
    int number;
public:
    void update(int num){
        number = num;
    }
    int getNum()const{
        return number;
    }
};

class DoubleNum:public NumObserver{
private:
    int number;
public:
    void update(int num){
        number = num*2;
    }
    int getNum()const{
        return number;
    }
};

class SquareNum:public NumObserver{
private:
    int number;
public:
    void update(int num){
        number = num*num;
    }
    int getNum() const{
        return number;
    }
};

#endif // NUMOBSERVER_H



NumWidgetViewer.h


#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<boost/scoped_ptr.hpp>
#include"NumController.h"
using namespace boost;

class NumController;

class NumWidgetViewer : public QWidget
{
    Q_OBJECT

public:
    explicit NumWidgetViewer(NumController* controller,QWidget *parent = 0);
    ~NumWidgetViewer();
    void updateNum(int num,int doubleNum,int squareNum);
protected slots:
    void on_decreaseButton_clicked();
    void on_increaseButton_clicked();
private:
    class NumWidgetViewerUi;
    scoped_ptr<NumWidgetViewerUi> mui;
    NumController* mController;
};

#endif // WIDGET_H



NumWidgetViewer.cpp


#include "NumWidgetViewer.h"
#include "ui_widget.h"

class NumWidgetViewer::NumWidgetViewerUi:public Ui::Widget{

};


NumWidgetViewer::NumWidgetViewer(NumController* controller,QWidget *parent):
    QWidget(parent),mController(controller)
{
    //init viewer
    mui.reset(new NumWidgetViewerUi);
    mui->setupUi(this);
    mui->numEdit->setEnabled(false);
    mui->DoubleEdit->setEnabled(false);
    mui->SquareEdit->setEnabled(false);
}

void NumWidgetViewer::on_decreaseButton_clicked(){
    mController->decreaseNum();
    update();
}

void NumWidgetViewer::on_increaseButton_clicked(){
    mController->increaseNum();
    update();
}

void NumWidgetViewer::updateNum(int num, int doubleNum, int squareNum){
    mui->numEdit->setText(QString::number(num));
    mui->DoubleEdit->setText(QString::number(doubleNum));
    mui->SquareEdit->setText(QString::number(squareNum));
}

NumWidgetViewer::~NumWidgetViewer()
{

}



NumController.h


#ifndef NUMCONTROLLER_H
#define NUMCONTROLLER_H

#include"Model.h"
#include"NumWidgetViewer.h"
#include<boost/scoped_ptr.hpp>
using namespace boost;

class NumWidgetViewer;

class NumController{
public:
    NumController();
    void increaseNum();
    void decreaseNum();
    void setNum(int num);
    void createView();
private:
    class NumControllerData;
    scoped_ptr<NumControllerData> mData;
    scoped_ptr<NumWidgetViewer> mViewer;
};

#endif // NUMCONTROLLER_H



NumController.cpp


#include"NumController.h"
#include"NumObserver.h"

class NumController::NumControllerData{
public:
    NumObserver *doubleNum;
    NumObserver *squareNum;
    NumObserver *num;
    Model *model;
    int number;
public:
    NumControllerData(){
        doubleNum = new DoubleNum;
        squareNum = new SquareNum;
        num = new Num;
        model = new NumModel;
        model->registerObserver(doubleNum);
        model->registerObserver(squareNum);
        model->registerObserver(num);
    }
};

NumController::NumController()
{
    //init model
    mData.reset(new NumControllerData);
    createView();
}

//init viewer
void NumController::createView(){
    mViewer.reset(new NumWidgetViewer(this));
    setNum(10);
    mViewer->show();
}

void NumController::increaseNum()
{
    setNum(mData->model->getNum()+1);
}

void NumController::decreaseNum()
{
    setNum(mData->model->getNum()-1);
}

void NumController::setNum(int num)
{
    mData->model->setNum(num);
    mData->model->notifyObserver();
    mViewer->updateNum(mData->num->getNum(),
                   mData->doubleNum->getNum(),
                   mData->squareNum->getNum());
}



main.cpp


#include <QtGui/QApplication>
#include "NumController.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    NumController* controller = new NumController;
    controller->createView();
    return a.exec();
}



[img]http://dl.iteye.com/upload/attachment/522478/f3774b89-64df-3d16-a06f-354b81f3ce20.png[/img]