MVC、MVP和MVVM模式
MVC模式中,视图和模型之间直接交互,而MVP模式下,视图与模型通过Presenter进行通信,MVVM则采用双向绑定,减少手动同步视图和模型的工作。每种模式都有其优缺点,适合不同规模和类型的项目。
### MVVM 与 MVP/MVC 的区别:
1. **数据绑定**:
- MVVM 强调 View 和 ViewModel 的自动同步。
- MVP/MVC 需要手动更新 View。
2. **View 的主动性**:
- MVVM 中,View 是完全被动的。
- MVP 中,View 需要通过 Presenter 更新。
- MVC 中,View 可以直接监听 Model 的变化。
3. **适用场景**:
- MVVM 更适合需要频繁更新 UI 的场景(如 GUI 应用)。
- MVP/MVC 更适合简单的逻辑控制。
1.MVC模式

-
Model 负责存储和管理数据。
-
View 负责显示数据。
-
Controller 负责处理用户输入并更新模型,然后通知视图更新显示。
1. 模型(Model)
模型负责管理应用程序的数据和业务逻辑。
// model.h
#ifndef MODEL_H
#define MODEL_Htypedef struct {int data;
} Model;void Model_init(Model *model);
void Model_setData(Model *model, int data);
int Model_getData(Model *model);#endif // MODEL_H
// model.c
#include "model.h"void Model_init(Model *model) {model->data = 0;
}void Model_setData(Model *model, int data) {model->data = data;
}int Model_getData(Model *model) {return model->data;
}
2. 视图(View)
视图负责显示数据给用户。
// view.h
#ifndef VIEW_H
#define VIEW_H#include "model.h"typedef struct {Model *model;
} View;void View_init(View *view, Model *model);
void View_display(View *view);#endif // VIEW_H
// view.c
#include "view.h"
#include <stdio.h>void View_init(View *view, Model *model) {view->model = model;
}void View_display(View *view) {printf("Data: %d\n", Model_getData(view->model));
}
3. 控制器(Controller)
控制器负责处理用户输入并更新模型。
// controller.h
#ifndef CONTROLLER_H
#define CONTROLLER_H#include "model.h"
#include "view.h"typedef struct {Model *model;View *view;
} Controller;void Controller_init(Controller *controller, Model *model, View *view);
void Controller_updateData(Controller *controller, int data);#endif // CONTROLLER_H
// controller.c
#include "controller.h"void Controller_init(Controller *controller, Model *model, View *view) {controller->model = model;controller->view = view;
}void Controller_updateData(Controller *controller, int data) {Model_setData(controller->model, data);View_display(controller->view);
}
4. 主程序
主程序将模型、视图和控制器组合在一起。
// main.c
#include "model.h"
#include "view.h"
#include "controller.h"int main() {Model model;View view;Controller controller;Model_init(&model);View_init(&view, &model);Controller_init(&controller, &model, &view);// 模拟用户输入Controller_updateData(&controller, 10);Controller_updateData(&controller, 20);return 0;
}
5. 输出结果
Data: 10
Data: 20
2.MVP模式

MVP(Model-View-Presenter)是MVC模式的一种变体,它将视图和模型之间的交互通过Presenter(主持人)来协调。
-
Model 负责存储和管理数据。
-
View 负责显示数据,并将用户输入传递给Presenter。
-
Presenter 负责处理用户输入,更新模型,并通知视图更新显示。
与MVC模式不同,MVP模式中视图和模型之间没有直接交互,所有的交互都通过Presenter来协调。这种设计使得视图和模型之间的耦合度更低,更易于测试和维护。
1. 模型(Model)
模型负责管理应用程序的数据和业务逻辑。
// model.h
#ifndef MODEL_H
#define MODEL_Htypedef struct {int data;
} Model;void Model_init(Model *model);
void Model_setData(Model *model, int data);
int Model_getData(Model *model);#endif // MODEL_H
// model.c
#include "model.h"void Model_init(Model *model) {model->data = 0;
}void Model_setData(Model *model, int data) {model->data = data;
}int Model_getData(Model *model) {return model->data;
}
2. 视图(View)
视图负责显示数据,并将用户输入传递给Presenter。
// view.h
#ifndef VIEW_H
#define VIEW_Htypedef struct {void (*displayData)(int data); // 显示数据的回调函数
} View;#endif // VIEW_H
3. Presenter(主持人)
Presenter负责处理视图的输入,更新模型,并通知视图更新显示
// presenter.h
#ifndef PRESENTER_H
#define PRESENTER_H#include "model.h"
#include "view.h"typedef struct {Model *model;View *view;
} Presenter;void Presenter_init(Presenter *presenter, Model *model, View *view);
void Presenter_updateData(Presenter *presenter, int data);#endif // PRESENTER_H
// presenter.c
#include "presenter.h"void Presenter_init(Presenter *presenter, Model *model, View *view) {presenter->model = model;presenter->view = view;
}void Presenter_updateData(Presenter *presenter, int data) {// 更新模型Model_setData(presenter->model, data);// 从模型获取数据并通知视图更新int currentData = Model_getData(presenter->model);presenter->view->displayData(currentData);
}
4. 主程序
主程序将模型、视图和Presenter组合在一起。
// main.c
#include <stdio.h>
#include "model.h"
#include "view.h"
#include "presenter.h"// 视图的具体实现
void displayData(int data) {printf("Current Data: %d\n", data);
}int main() {Model model;View view;Presenter presenter;// 初始化Model_init(&model);view.displayData = displayData; // 设置视图的回调函数Presenter_init(&presenter, &model, &view);// 模拟用户输入Presenter_updateData(&presenter, 10);Presenter_updateData(&presenter, 20);return 0;
}
5.输出结果
Current Data: 10
Current Data: 20
3.MVVM模式

MVVM(Model-View-ViewModel)是一种常用于GUI应用程序的设计模式,它将视图(View)与模型(Model)通过视图模型(ViewModel)进行解耦。MVVM的核心思想是通过数据绑定将视图和视图模型连接起来,但由于C语言本身不支持数据绑定等高级特性,我们需要通过手动方式模拟MVVM的行为。
-
Model 负责存储和管理数据。
-
View 负责显示数据,并将用户输入传递给视图模型。
-
ViewModel 负责将模型的数据转换为视图可以显示的形式,并处理视图的输入。
在MVVM模式中,视图和模型之间没有直接交互,所有的交互都通过视图模型来协调。视图模型通过回调函数通知视图更新显示,从而实现了视图和模型的解耦。
1. 模型(Model)
模型负责管理应用程序的数据和业务逻辑。
// model.h
#ifndef MODEL_H
#define MODEL_Htypedef struct {int data;
} Model;void Model_init(Model *model);
void Model_setData(Model *model, int data);
int Model_getData(Model *model);#endif // MODEL_H
// model.c
#include "model.h"void Model_init(Model *model) {model->data = 0;
}void Model_setData(Model *model, int data) {model->data = data;
}int Model_getData(Model *model) {return model->data;
}
2. 视图模型(ViewModel)
视图模型负责将模型的数据转换为视图可以显示的形式,并处理视图的输入。
// viewmodel.h
#ifndef VIEWMODEL_H
#define VIEWMODEL_H#include "model.h"typedef struct {Model *model;void (*onDataChanged)(int data); // 数据改变时的回调函数
} ViewModel;void ViewModel_init(ViewModel *viewModel, Model *model);
void ViewModel_setData(ViewModel *viewModel, int data);
int ViewModel_getData(ViewModel *viewModel);#endif // VIEWMODEL_H
// viewmodel.c
#include "viewmodel.h"void ViewModel_init(ViewModel *viewModel, Model *model) {viewModel->model = model;viewModel->onDataChanged = NULL; // 初始化为空
}void ViewModel_setData(ViewModel *viewModel, int data) {//非常很重要,关键的一笔!!// 更新模型Model_setData(viewModel->model, data);// 通知视图数据已改变if (viewModel->onDataChanged != NULL) {viewModel->onDataChanged(data);}
}int ViewModel_getData(ViewModel *viewModel) {return Model_getData(viewModel->model);
}
3. 视图(View)
视图负责显示数据,并将用户输入传递给视图模型。
// view.h
#ifndef VIEW_H
#define VIEW_H#include "viewmodel.h"typedef struct {ViewModel *viewModel;
} View;void View_init(View *view, ViewModel *viewModel);
void View_display(View *view);
void View_userInput(View *view, int data);#endif // VIEW_H
// view.c
#include "view.h"
#include <stdio.h>// 数据改变时的回调函数
static void onDataChanged(int data) {printf("Data Updated: %d\n", data);
}void View_init(View *view, ViewModel *viewModel) {view->viewModel = viewModel;viewModel->onDataChanged = onDataChanged; // 设置回调函数
}void View_display(View *view) {int data = ViewModel_getData(view->viewModel);printf("Current Data: %d\n", data);
}void View_userInput(View *view, int data) {// 将用户输入传递给视图模型ViewModel_setData(view->viewModel, data);
}
4. 主程序
主程序将模型、视图模型和视图组合在一起。
// main.c
#include "model.h"
#include "viewmodel.h"
#include "view.h"int main() {Model model;ViewModel viewModel;View view;// 初始化Model_init(&model);ViewModel_init(&viewModel, &model);View_init(&view, &viewModel);// 显示初始数据View_display(&view);// 模拟用户输入View_userInput(&view, 10);View_userInput(&view, 20);return 0;
}
5. 输出结果
Current Data: 0
Data Updated: 10
Data Updated: 20
**在deep seek协助下
相关文章:
MVC、MVP和MVVM模式
MVC模式中,视图和模型之间直接交互,而MVP模式下,视图与模型通过Presenter进行通信,MVVM则采用双向绑定,减少手动同步视图和模型的工作。每种模式都有其优缺点,适合不同规模和类型的项目。 ### MVVM 与 MVP…...
shiro学习五:使用springboot整合shiro。在前面学习四的基础上,增加shiro的缓存机制,源码讲解:认证缓存、授权缓存。
文章目录 前言1. 直接上代码最后在讲解1.1 新增的pom依赖1.2 RedisCache.java1.3 RedisCacheManager.java1.4 jwt的三个类1.5 ShiroConfig.java新增Bean 2. 源码讲解。2.1 shiro 缓存的代码流程。2.2 缓存流程2.2.1 认证和授权简述2.2.2 AuthenticatingRealm.getAuthentication…...
负载均衡器高可用部署
Haproxy 和 Keepalived安装Haproxy配置文件准备Keepalived配置及健康检查启动Haproxy & Keepalived服务继续上一篇文章《K8S集群架构及主机准备》,下面介绍负载均衡器搭建过程 Haproxy 和 Keepalived安装 在负载均衡器两个主机上安装即可 apt install haproxy keepalived…...
属性编程与权限编程
问题 如何获取文件的大小,时间戳以及类型等信息? 再论 inode 文件的物理载体是硬盘,硬盘的最小存储单元是扇区 (每个扇区 512 字节) 文件系统以 块 为单位(每个块 8 个扇区) 管理文件数据 文件元信息 (创建者、创建日期、文件大小&#x…...
用 HTML、CSS 和 JavaScript 实现抽奖转盘效果
顺序抽奖 前言 这段代码实现了一个简单的抽奖转盘效果。页面上有一个九宫格布局的抽奖区域,周围八个格子分别放置了不同的奖品名称,中间是一个 “开始抽奖” 的按钮。点击按钮后,抽奖区域的格子会快速滚动,颜色不断变化…...
R语言绘制有向无环图(DAG)
有向无环图(Directed Acyclic Graph,简称DAG)是一种特殊的有向图,它由一系列顶点和有方向的边组成,其中不存在任何环路。这意味着从任一顶点出发,沿着箭头方向移动,你永远无法回到起始点。 从流…...
报错Too many open files
1、先查看系统最大打开文件数 # 查看当前系统打开文件最大数 # ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signal…...
Spring Web MVC基础第一篇
目录 1.什么是Spring Web MVC? 2.创建Spring Web MVC项目 3.注解使用 3.1RequestMapping(路由映射) 3.2一般参数传递 3.3RequestParam(参数重命名) 3.4RequestBody(传递JSON数据) 3.5Pa…...
129.求根节点到叶节点数字之和(遍历思想)
Problem: 129.求根节点到叶节点数字之和 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的先序遍历) 直接利用二叉树的先序遍历,将遍历过程中的节点值先利用字符串拼接起来遇到根节点时再转为数字并累加起来,在归的过程中…...
unity中的动画混合树
为什么需要动画混合树,动画混合树有什么作用? 在Unity中,动画混合树(Animation Blend Tree)是一种用于管理和混合多个动画状态的工具,包括1D和2D两种类型,以下是其作用及使用必要性的介绍&…...
AWS EMR使用Apache Kylin快速分析大数据
在AWS Elastic MapReduce(EMR)集群上部署和使用Apache Kylin,以实现对大规模数据集的快速分析,企业可以充分利用云计算的强大资源和Kylin的数据分析能力,实现快速、高效的数据分析。以下是该案例的详细步骤和要点&…...
MySQL存储过程和存储函数_mysql 存储过 call proc_stat_data(3,null)
2)很难调试存储过程。只有少数数据库管理系统允许调试存储过程。不幸的是,MySQL不提供调试存储过程的功能。 1.2 数据准备 创建数据库: DEFAULT CHARACTER SET utf8; use test;这里记得设置编码! 创建测试表: DROP…...
spacemacs gnuplot
个人博客地址:spacemacs gnuplot | 一张假钞的真实世界 环境 Ubuntu 16.10Emacs 24 安装过程 spacemacs安装 安装Emacs sudo apt-get install emacs 安装spacemacs (1)如果已经存在Emacs配置文件,首先备份: c…...
Flink2支持提交StreamGraph到Flink集群
最近研究Flink源码的时候,发现Flink已经支持提交StreamGraph到集群了,替换掉了原来的提交JobGraph。 新增ExecutionPlan接口,将JobGraph和StreamGraph作为实现。 Flink集群Dispatcher也进行了修改,从JobGraph改成了接口Executio…...
Kotlin 使用 Springboot 反射执行方法并自动传参
在使用反射的时候,执行方法的时候在想如果Springboot 能对需要执行的反射方法的参数自动注入就好了。所以就有了下文。 知识点 获取上下文通过上下文获取 Bean通过上下文创建一个对象,该对象所需的参数由 Springboot 自己注入 创建参数 因为需要对反…...
索罗斯的“反身性”(Reflexivity)理论:市场如何扭曲现实?(中英双语)
索罗斯的“反身性”(Reflexivity)理论:市场如何扭曲现实? 一、引言:市场是镜子,还是哈哈镜? 在传统经济学中,市场通常被认为是一个理性、有效的反映现实的系统。按照经典经济学理论…...
Vue 入门到实战 七
第7章 渲染函数 目录 7.1 DOM树 7.2 什么是渲染函数 7.3 h()函数 7.3.1 基本参数 7.3.2 约束 7.3.3 使用JavaScript代替模板功能 7.1 DOM树 7.2 什么是渲染函数 在多数情况下,Vue推荐使用模板template来创建HTML。然而在一些应用场景中,需要使用J…...
系统学习算法: 专题八 二叉树中的深搜
深搜其实就是深度优先遍历(dfs),与此相对的还有宽度优先遍历(bfs) 如果学完数据结构有点忘记,如下图,左边是dfs,右边是bfs 而二叉树的前序,中序,后序遍历都可…...
进程、线程、内存和IO模型的概念详解
进程、线程、内存和IO模型的概念详解 1 进程与线程1.1 进程1.1.1 进程分类1.1.2 进程的状态和转换1.1.3 僵尸进程和孤儿进程的区别1.1.4 进程之间的通信1.1.5 用户态和内核态1.1.6 用户空间和内核空间 1.2 线程1.2.1 线程的状态和转换1.2.2 进程与线程的区别 1.3 多进程和多线程…...
DeepSeek:AI领域的创新先锋
在人工智能领域,DeepSeek正以其独特的创新技术引领着行业的发展。作为一款高性能、低成本的AI模型,DeepSeek在架构设计、训练优化和应用场景等多个方面都展现出了显著的创新点。这些创新不仅使其在技术上取得了突破,也为AI的普及化和应用拓展…...
Labelme转Voc、Coco
Q:在github找的cv代码基本都是根据现有且流行的公共数据集格式组织的训练数据集,这导致我使用labelme标注好之后需要我们重新组织数据集 labelme2coco #!/usr/bin/env pythonimport argparse import collections import datetime import glob import j…...
pytorch实现变分自编码器
人工智能例子汇总:AI常见的算法和例子-CSDN博客 变分自编码器(Variational Autoencoder, VAE)是一种生成模型,属于深度学习中的无监督学习方法。它通过学习输入数据的潜在分布(Latent Distribution)&…...
使用 Numpy 自定义数据集,使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数
1. 导入必要的库 首先,导入我们需要的库:Numpy、Pytorch 和相关工具包。 import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import accuracy_score, recall_score, f1_score2. 自定义数据集 …...
JVM方法区
一、栈、堆、方法区的交互关系 二、方法区的理解: 尽管所有的方法区在逻辑上属于堆的一部分,但是一些简单的实现可能不会去进行垃圾收集或者进行压缩,方法区可以看作是一块独立于Java堆的内存空间。 方法区(Method Area)与Java堆一样,是各个…...
【Python】第七弹---Python基础进阶:深入字典操作与文件处理技巧
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】【Python】 目录 1、字典 1.1、字典是什么 1.2、创建字典 1.3、查找 key 1.4、新增/修改元素 1.5、删除元素 1.6、遍历…...
指导初学者使用Anaconda运行GitHub上One - DM项目的步骤
以下是指导初学者使用Anaconda运行GitHub上One - DM项目的步骤: 1. 安装Anaconda 下载Anaconda: 让初学者访问Anaconda官网(https://www.anaconda.com/products/distribution),根据其操作系统(Windows、M…...
在实际开发中,如何正确使用 INT(1) 和 INT(10)
在实际开发中,如何正确使用 INT(1) 和 INT(10) 前言 在数据库设计和开发过程中,数据类型的选择至关重要。 最近,我在工作中遇到了一个关于MySQL中INT类型的误解问题,这让我意识到很多开发者对INT类型的理解存在误区。 本文将深…...
像接口契约文档 这种工件,在需求 分析 设计 工作流里面 属于哪一个工作流
οゞ浪漫心情ゞο(20***328) 2016/2/18 10:26:47 请教一下,像接口契约文档 这种工件,在需求 分析 设计 工作流里面 属于哪一个工作流? 潘加宇(35***47) 17:17:28 你这相当于问用例图、序列图属于哪个工作流,看内容。 如果你的&quo…...
GAMES101学习笔记(六):Geometry 几何(基本表示方法、曲线与曲面、网格处理)
文章目录 几何的表示方法隐式几何 Implicit Geometry代数曲面(Algebraic surface)构造实体几何CSG(Constructive Solid Geometry)距离函数(Distance Function)水平集方法(Level Set Methods)分型几何(Fractal) 显式几何 Explicit Geometry点云(Point Cloud)多边形网格(Polygon …...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.24 随机宇宙:生成现实世界数据的艺术
1.24 随机宇宙:生成现实世界数据的艺术 目录 #mermaid-svg-vN1An9qZ6t4JUcGa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-vN1An9qZ6t4JUcGa .error-icon{fill:#552222;}#mermaid-svg-vN1An9qZ6t4JUc…...
