MVC模型简单解读
来源:互联网 发布:保留小数位数的函数sql 编辑:程序博客网 时间:2024/06/08 19:47
MVC简介
MVC全称为Model View Controller(模型-视图-控制器)。M是指业务模型,V是指用户界面,C则是控制器。MVC主要用于UI的相关设计中,它用业务逻辑、数据、界面显示分离的方法组织代码。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
要点
1.MVC是有数个设计模式结合起来的。
2.MVC结合了观察者模式、策略模式和组合模式。
3.模型使用观察者模式,以便观察者更新,同时保持两者之间解耦。
4.视图为模型的观察者,同一个模式可以使用不同的视图,甚至可以同时使用多个视图。
5.控制器是视图的策略,视图可以使用不同的控制器实现,得到不同的行为。
6.控制器收到视图的数据后,会经过“解读”后再发送给模型。
7.视图一般使用组合模式实现用户界面。
示意图
① 视图用于和用户交互
视图是模型的窗口,当用户对视图操作后,视图就告诉控制器用户的操作,控制器会负责处理用户的请求。
② 控制器要求模型改变状态
控制器解读用户的请求之后,便告知模型做出相应的动作。
③ 控制器也可能要求视图做改变
当控制器收到视图的某一动作后,可能需要告诉视图做出相应的改变,比如界面上的某一个按钮变得无效。
④ 当模型状态改变时,模型会通知视图
当模型的状态改变时(可能是因为用户的操作,也可能是模型自己内部状态的改变),会通知视图它的状态已经改变。
⑤ 视图向模型询问状态
视图可以直接从模型取得它的显示状态。视图做这个动作一般有两个因素:一是在模型通知视图它的状态改变;二是控制器请求视图改变。
示例
如上图所示,两个对话框是由View创建出来的。Control View 可以控制Display View中显示的内容,点击“Start”按钮后可以在Control View中输入数值,点击“Set”按钮便可以设置到Display View中。若点击“Stop”按钮后,无法再设置值到Display View中。“Increase”按钮可以让Display View中的数值加一,“Decrease”可以让Display View中的数值减一。类图如下所示:
Model:实现了可观察者接口,下面的方法允许观察者注册或者删除自己。
void registerObserver(IObserver* observer);void removeObserver(IObserver* observer);
另开放下面的接口供Controller可以改变Model的状态:
void initialize();void on();void off();void setValue(int value);
开放下面的接口供View可以获取Model的状态:
int getValue();
View:为了强调包含模型的视图的界面和包含其他用户控制的界面的差异,将界面设计成两个窗口(其实是一个类)。
View同时包含了IModel和IController的指针,但两者的作用完全不同,如下所示:
IModel* m_model; // 包含模型的指针作用:1.向模型注册观察者 2.从模型获取数据IController* m_controller; // 控制器为视图的策略(所有用户操作交给控制器处理)
View同样开放一些接口,供Controller来改变View的状态:
void enableStartBtn();void disableStartBtn();void enableStopBtn();void disableStopBtn();
View为模型的观察者,必须实现观察者接口,以便在Model状态改变时通知View:
void updateValue();
View在用户操作界面是会调用Controller如下所示的接口:
void start();void stop();void increaseValue();void decreaseValue();void setValue(int value);
控制器:Controller是策略,把它插进View中,让View变得聪明。控制器是连接View和Model的中间部件,View将用户的操作传给Controller,Controller ”解读“之后再传给Model。
Controller是通过View的构造函数传入View的。为了Controller能够改变View的状态,在Controller注册为View的策略的时候,View必须将自己的指针设置给Controller,如下所示:
View::View(IController* controller, IModel* model, QWidget *parent) : QWidget(parent){ this->m_controller = controller; // 控制器作为视图的策略,让视图变得聪明 m_controller->setView(this); // 把View的指针设置到控制器,用于控制器改变视图的状态 // 其他操作}
下面列出全部代码(本示例是基于Qt5.6开发的):
IObserver.h
#ifndef IOSERVER_H#define IOSERVER_H// 观察者接口class IObserver{public: IObserver() {} virtual ~IObserver() {} virtual void updateValue() = 0;};#endif
Model.h
#ifndef MODEL_H#define MODEL_H#include "IObserver.h"#include <QList>// 模型接口class IModel{public: IModel() {} virtual ~IModel() {} virtual void initialize() = 0; virtual void on() = 0; // 开始显示 virtual void off() = 0; // 停止显示 virtual void setValue(int value) = 0; virtual int getValue() = 0; virtual void registerObserver(IObserver* observer) = 0; // 注册观察者 virtual void removeObserver(IObserver* observer) = 0; // 删除观察者 virtual void notify() = 0; // 通知观察者};class Model : public IModel{private: QList<IObserver*> m_observers; int m_value;public: Model(); void initialize(); void on(); void off(); void setValue(int value); int getValue(); void registerObserver(IObserver* observer); void removeObserver(IObserver* observer); void notify();};#endif // MODEL_H
Model.cpp
#include "Model.h"#include "View.h"Model::Model(){ m_value = 0;}void Model::initialize(){}void Model::on(){ setValue(90);}void Model::off(){ setValue(0);}void Model::setValue(int value){ this->m_value = value; notify();}int Model::getValue(){ return m_value;}void Model::registerObserver(IObserver* observer){ m_observers.append(observer);}void Model::removeObserver(IObserver* observer){ m_observers.removeOne(observer);}void Model::notify(){ for (int i=0; i<m_observers.size(); i++) { m_observers[i]->updateValue(); }}
View.h
#ifndef VIEW_H#define VIEW_H#include "IObserver.h"#include <QWidget>#include <QLineEdit>#include <QPushButton>#include <QDialog>#include <QLabel>class IModel;class IController;class View : public QWidget, public IObserver{ Q_OBJECTprivate: IModel* m_model; // 包含模型的指针作用:1.向模型注册观察者 2.从模型获取数据 IController* m_controller; // 控制器为视图的策略(所有用户操作交给控制器处理)private: QLineEdit* inputEdit; QPushButton* startBtn; QPushButton* stopBtn; QDialog* displayDialog; QLabel* displayLabel; void constructUI();protected: void closeEvent(QCloseEvent *event);public: View(IController* controller, IModel* model, QWidget *parent = 0); ~View(); void enableStartBtn(); void disableStartBtn(); void enableStopBtn(); void disableStopBtn(); void updateValue();protected slots: void onSetBtn(); void onStartBtn(); void onStopBtn(); void onIncreaseBtn(); void onDecreaseBtn();};#endif // VIEW_H
View.cpp
#include "View.h"#include "Model.h"#include "Controller.h"#include <QGridLayout>View::View(IController* controller, IModel* model, QWidget *parent) : QWidget(parent){ this->m_controller = controller; // 控制器作为视图的策略,让视图变得聪明 this->m_model = model; m_model->registerObserver(this); // 向模型注册自己为观察者 m_controller->setView(this); // 把View的指针设置到控制器,用于控制器改变视图的状态 constructUI(); disableStopBtn(); enableStartBtn();}View::~View(){}void View::updateValue(){ int value = m_model->getValue(); if (0 == value) { displayLabel->setText("Offline"); } else { displayLabel->setText("Current value: " + QString::number(value)); }}void View::constructUI(){ this->resize(300, 200); inputEdit = new QLineEdit(); QPushButton* setBtn = new QPushButton(); setBtn->setText("Set"); connect(setBtn, SIGNAL(clicked()), this, SLOT(onSetBtn())); startBtn = new QPushButton(); startBtn->setText("Start"); connect(startBtn, SIGNAL(clicked()), this, SLOT(onStartBtn())); stopBtn = new QPushButton(); stopBtn->setText("Stop"); connect(stopBtn, SIGNAL(clicked()), this, SLOT(onStopBtn())); QPushButton* increaseBtn = new QPushButton(); increaseBtn->setText("Increase"); connect(increaseBtn, SIGNAL(clicked()), this, SLOT(onIncreaseBtn())); QPushButton* decreaseBtn = new QPushButton(); decreaseBtn->setText("Decrease"); connect(decreaseBtn, SIGNAL(clicked()), this, SLOT(onDecreaseBtn())); QGridLayout* mainLayout = new QGridLayout(this); mainLayout->addWidget(inputEdit, 0, 0, 1, 3); mainLayout->addWidget(setBtn, 0, 3); mainLayout->addWidget(startBtn, 1, 0); mainLayout->addWidget(stopBtn, 1, 1); mainLayout->addWidget(increaseBtn, 1, 2); mainLayout->addWidget(decreaseBtn, 1, 3); this->setWindowTitle("Control View"); this->resize(350, 70); this->show(); displayDialog = new QDialog(); displayLabel = new QLabel(displayDialog); displayDialog->setWindowTitle("Display View"); displayDialog->resize(200, 50); displayLabel->resize(150, 20); displayLabel->move(10, 10); displayDialog->show();}void View::enableStartBtn(){ startBtn->setEnabled(true);}void View::disableStartBtn(){ startBtn->setEnabled(false);}void View::enableStopBtn(){ stopBtn->setEnabled(true);}void View::disableStopBtn(){ stopBtn->setEnabled(false);}void View::onSetBtn(){ QString string = inputEdit->text(); if (string.isEmpty()) { return; } int value = string.toInt(); m_controller->setValue(value);}void View::onStartBtn(){ m_controller->start();}void View::onStopBtn(){ m_controller->stop();}void View::onIncreaseBtn(){ m_controller->increaseValue();}void View::onDecreaseBtn(){ m_controller->decreaseValue();}void View::closeEvent(QCloseEvent *){ displayDialog->close(); delete displayDialog;}
Controller.h
#ifndef CONTROLLER_H#define CONTROLLER_H#include "Model.h"#include "View.h"class IController{public: IController() {} virtual ~IController() {} virtual void start() = 0; virtual void stop() = 0; virtual void increaseValue() = 0; virtual void decreaseValue() = 0; virtual void setValue(int value) = 0; virtual void setView(View* view) = 0;};class Controller : public IController{private: IModel* m_model; View* m_view;public: Controller(IModel* model); void start(); void stop(); void increaseValue(); void decreaseValue(); void setValue(int value); void setView(View* view);};#endif // CONTROLLER_H
Controller.cpp
#include "Controller.h"Controller::Controller(IModel *model){ this->m_model = model;}void Controller::start(){ m_model->on(); m_view->disableStartBtn(); m_view->enableStopBtn();}void Controller::stop(){ m_model->off(); m_view->enableStartBtn(); m_view->disableStopBtn();}void Controller::increaseValue(){ int value = m_model->getValue(); m_model->setValue(value+1);}void Controller::decreaseValue(){ int value = m_model->getValue(); m_model->setValue(value-1);}void Controller::setValue(int value){ m_model->setValue(value);}void Controller::setView(View* view){ m_view = view;}
main.cpp
#include "View.h"#include "Model.h"#include "Controller.h"#include <QApplication>int main(int argc, char *argv[]){ QApplication a(argc, argv); IModel* model = new Model(); IController* controller = new Controller(model); View* view = new View(controller, model); return a.exec();}
MVC.pro
QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = MVCTEMPLATE = appSOURCES += main.cpp\ View.cpp \ Controller.cpp \ Model.cppHEADERS += View.h \ Controller.h \ Model.h \ IObserver.h
测试
如下为测试结果:
- MVC模型简单解读
- MVC模型简单介绍
- MVC模型简单案例
- Apache OFBiz源码解读之MVC模型
- Apache OFBiz源码解读之MVC模型
- MVC模型的简单理解
- CI 搭建简单的MVC模型示例
- MVC模型
- MVC模型
- mvc模型
- MVC模型
- MVC模型
- MVC模型
- MVC模型
- MVC模型
- MVC模型
- MVC模型
- 简单介绍下mvc的路由,加载控制器,模型,视图
- 从源码剖析PopupWindow 兼容Android 6.0以上版本点击外部不消失
- android隐藏关闭软键盘
- javaWeb实战教程8-用户模块的编码实现
- 安卓进入页面避免软键盘弹出的解决办法
- 先搞一波kotlin,看它怎么说
- MVC模型简单解读
- javaWeb实战教程9-商品分类模块的编码实现
- javaWeb实战教程10-商品模块的编码实现
- 使用redis优化性能之注册和登录
- Kali的学习笔记
- android不用第三方如何打开word,ppt?
- 考研机试题目-清华大学-28道
- ViewRootImpl类分析View绘制的流程
- Win7系统cmd输入ls命令提示不是内部或外部命令怎么办