为了解决一个类实现所有功能的缺陷,我们把application分为2个部分。一个部分业务逻辑,一个部分视觉渲染和交互。这2个类在学术上被称为document view 或者 model

delegate。

   Document类用来处理业务逻辑,和视觉渲染、GUI事件没有一点关系。它简单的存储应用程序的状态,提供接口获得状态并根据应用程序规则改变状态。另外,提供机制告知相关对象,应用程序状态改变。

  View类处理事件和图像渲染。提供对 Document类的操作,界面改变和 Document类中状态改变同步。

   Document View设计模式实现状态和图像显示分离,它们能单独的改变。Document类成为 non-GUI单元,能单独的工作和检测。任何View通过notification system保持和Document内容一致,并根据Document内容 负责图像呈现和用户交互。

  这种设计消除了一些对单个类实现的担忧,对状态和业务逻辑的测试变得更容易:通过调用Document类中的方法。此Document对象现在是独立的,如果需要的话,可以和不同的View工作。代价就是告知View,Document中状态改变(notification system)。

代码如下:

model.h

#include <QSet>
#include <view.h> class View; class Model
{
public:
Model();
int getClickTimes() const;
void setClickTimes(int value);
void incrementClickTimes();
void addListener(View *v);
void removeListener(View *v); private:
int m_clickTimes;
QSet<View *> listeners; //set容器避免重复
void notifyListener();
}; #endif // MODEL_H

model.cpp

#include "model.h"

Model::Model()
{
m_clickTimes = ;
notifyListener();
} int Model::getClickTimes() const
{
return m_clickTimes;
} void Model::setClickTimes(int value)
{
if(m_clickTimes != value)
m_clickTimes = value;
notifyListener();
} void Model::incrementClickTimes()
{
m_clickTimes++;
notifyListener();
} void Model::addListener(View *v)
{
listeners.insert(v);
notifyListener();
} void Model::removeListener(View *v)
{
listeners.remove(v);
} void Model::notifyListener()
{
foreach (View *v, listeners) {
v->notify();
}
}

view.h

#ifndef VIEW_H
#define VIEW_H #include <QPushButton>
#include <model.h> class Model; class View : public QPushButton
{
Q_OBJECT
public:
explicit View(QWidget *parent = );
void notify(); protected:
void mouseReleaseEvent(QMouseEvent *e); private:
Model *model;
}; #endif // VIEW_H

view.cpp

#include "view.h"

View::View(QWidget *parent) :
QPushButton(parent)
{
model = new Model();
model->addListener(this);
} void View::mouseReleaseEvent(QMouseEvent *e)
{
model->incrementClickTimes();
} void View::notify()
{
setText(QString::number(model->getClickTimes()));
}

main.cpp

#include <view.h>
#include <QApplication> int main(int argc, char *argv[])
{
QApplication a(argc, argv);
View v;
v.show(); return a.exec();
}

思考:

1.Model类只处理数据,View类处理事件和如何显示程序。

2.Model类中有一个容器 listeners,存放需要显示数据的类,每当应用程序状态改变时(m_clickTimes改变),告诉那些类,应用程序状态改变啦!

3.View类 mouseRelease函数处理事件,notify函数显示数据。

3.文档视图:从gui分割状态的更多相关文章

  1. MFC文档视图结构学习笔记

    文档/视图概述 为了统一和简化数据处理方法,Microsoft公司在MFC中提出了文档/视图结构的概念,其产品Word就是典型的文档/视图结构应用程序 MFC通过其文档类和视图类提供了大量有关数据处理 ...

  2. 深入分析MFC文档视图结构(项目实践)

    k_eckel:http://www.mscenter.edu.cn/blog/k_eckel 文档视图结构(Document/View Architecture)是MFC的精髓,也是Observer ...

  3. MFC单文档视图程序简介

    在视图应用程序中,应用程序的数据由文档对象代表,数据的视图由视图对象代表.MFC的Cdocument类是文档对象的基类,Cview类是视图对象的基类.应用程序的主窗口,其操作功能在MFC的Cframe ...

  4. 文档/视图(01):第一个Demo

    学习文档视图编程的第一个demo,程序比较简单,主要对文档模板,文档,视图等相互关系的一个了解. 功能:菜单添加一个[操作]项,然后新建四份空白文档,点击[操作]之后,在四份空白文档上面各绘制一个Bu ...

  5. DotNetBar中dotNetBarManager设置窗口 实现单文档视图界面

    本人想设计一个但文档视图的界面: |--------------------------------------------------------------- |   Ribbon Bar |-- ...

  6. mfc创建文档视图过程

    一.如何创建文档视图界面: 创建新的文档视图界面,只需要调用CDocTemplate::OpenDocumentFile(strpath)即可.(strpath为要打开的文档路径,如果是NULL,则生 ...

  7. MFC中 创建基于CFormView的文档视图程序

    在MFC中可以创建多种类型的窗口程序,如对话框程序.单文档结构程序(非文档/视图结构).单文档(文档/视图结构)以及多文档视图结构程序等. 在编写一般的小工具时,我们的首选显然是对话框程序,不过基于对 ...

  8. 如何优雅的写UI——(2)MFC下基于CFormView的文档视图程序

    在MFC中可以创建多种类型的窗口程序,如对话框程序.单文档结构程序(非文档/视图结构).单文档(文档/视图结构)以及多文档视图结构程序等. 在编写一般的小工具时,我们的首选显然是对话框程序,不过基于对 ...

  9. MFC文档视图中窗口切换 (2012-05-11 18:32:48)

    在文档试图应用程序,有时需要在工作区切换试图,以下就是如何切换试图了 .创建要切换的视图类,同时把构造函数,Create函数改变为public .在需要切换试图的动作响应中,加入切换代码,一般是在CM ...

随机推荐

  1. 剑指offer--18.从尾到头打印链表

    递归,逐个加到后面 ------------------------------------------------------------------------------ 时间限制:1秒 空间限 ...

  2. Codeforces Round #266 (Div. 2)B(暴力枚举)

    很简单的暴力枚举,却卡了我那么长时间,可见我的基本功不够扎实. 两个数相乘等于一个数6*n,那么我枚举其中一个乘数就行了,而且枚举到sqrt(6*n)就行了,这个是暴力法解题中很常用的性质. 这道题找 ...

  3. charles mock数据时解决乱码问题

    1.新建文件,不要后缀名 2.下载Notepad++ 软件,使用该软件打开文件:设置:格式---->以UTF-8无BOM格式编码 3.正常在文件中写入数据,maplocal 就可以了

  4. 在VS2013上配置OpenCV1.0

    OpenCV1.0版(下载)基本上已经是老掉牙了,但是不想装新版,只是因为任性.所以就有了这样一个新老搭配.装完回想起来还是挺简单的,但是还是费了我一晚上,所以有必要记录一下.         先在电 ...

  5. innoDB 下主键的思考

    主键 表中每一行都应该有可以唯一标识自己的一列(或一组列). 一个顾客可以使用顾客编号列,而订单可以使用订单ID,雇员可以使用雇员ID 或 雇员社会保险号. 主键(primary key) 一列(或一 ...

  6. Python学习笔记一(基础信息)

    目录 输入输出 数据类型和变量 整数 浮点数 字符串 布尔值 空值 变量 常量 小结 欢迎关注我的博客我在马路边 说明:此笔记不是从零开始,在学习的过程中感觉需要记录一些比较重要和需要重复浏览的信息, ...

  7. GO语言heap剖析及利用heap实现优先级队列

    GO语言heap剖析 本节内容 heap使用 heap提供的方法 heap源码剖析 利用heap实现优先级队列 1. heap使用 在go语言的标准库container中,实现了三中数据类型:heap ...

  8. nginx之 [error] 6702#0:XXX is forbidden (13: Permission denied)

    问题描述: 配置完 nginx 两个虚拟机后,客户端能够访问原始的server ,新增加的 server 虚拟机 不能够访问,报错如下页面 解决过程: 1. 查看报错日志[root@mysql03 n ...

  9. 在Linux上利用core dump和GDB调试segfault

    时常会遇到段错误(segfault),调试非常费劲,除了单元测试和基本测试外,有些时候是在在线环境下,没有基本开发和测试工具,这就需要调试的技能.以前介绍过使用strace进行系统调试和追踪<l ...

  10. [转载]嵌入式linux下操作GPIO

    本文转自:http://blog.csdn.net/mirkerson/article/details/8464231 在嵌入式设备中对GPIO的操作是最基本的操作.一般的做法是写一个单独驱动程序,网 ...