MVC与MVVM 架构

文章目录

MVC

MVC是一种将应用程序分为三个核心组件的架构模式:

  • Model(模型) ------ 负责数据, 不关心数据怎么显示
  • View(视图) ------ 负责界面显示,只负责把数据显示出来,
  • Controller(控制器) ------ 负责处理用户输入并协调 Model 和 View,用户交互和业务逻辑

通过Controller 把 Model 和 View 进行解耦

MVC 的大致工作流程

用户与 View 交互(例如点击按钮)。

Controller 捕捉到动作,向后端发送数据,后端返回的数据 (修改 Model) Model 改变后,在通知 View 更新显示。

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>

// --- 1. Model (模型) ---
// 负责存储数据,并在数据改变时通知观察者
class Model {
private:
    int data;
public:
    Model(int d) : data(d) {}
    
    void setData(int d) {
        data = d;
        std::cout << "[Model] 数据更新为: " << data << std::endl;
    }
    
    int getData() const { return data; }
};

// --- 2. View (视图) ---
// 负责数据的显示
class View {
public:
    void render(int data) {
        std::cout << "[View] 屏幕显示当前数值: " << data << std::endl;
    }
};

// --- 3. Controller (控制器) ---
// 负责逻辑中转
class Controller {
private:
    Model& model;
    View& view;

public:
    Controller(Model& m, View& v) : model(m), view(v) {}

    // 模拟用户输入处理
    void onUserAction(int newValue) {
        std::cout << "[Controller] 接收到用户输入: " << newValue << std::endl;
        model.setData(newValue);
        updateView();
    }

    void updateView() {
        view.render(model.getData());
    }
};

// --- 程序入口 ---
int main() {
    // 初始化
    Model model(10);
    View view;
    Controller controller(model, view);

    // 初始显示
    controller.updateView();

    std::cout << "-------------------------------" << std::endl;

    // 模拟用户操作:将数值改为 100
    controller.onUserAction(100);

    return 0;
}

优点与缺点

  • 优点

最大的优点已经说过了就是通过Controller 把 Model 和 View 进行解耦,把业务逻辑、数据、界面分离

  • 缺点

1️⃣ 所有逻辑都堆到 Controller上了,如 业务逻辑,数据处理,UI控制,结果就是 变成"上帝类,难维护。 久而久之就变成加入MVC架构前的代码臃肿问题,非常难维护。Controller 依赖太多。这个是最明显的缺点。

2️⃣ View 可能直接访问 Model


在小型项目上可以采取MVC架构

随之 引出MVVM 架构


MVVM

  • Model(模型) :

表示应用程序的数据负责处理数据的存取、处理和操作,Model并不直接与UI层交互,它只暴露一些接口供ViewModel层调用,使得ViewModel可以获取所需的数据。

  • View (视图):

主要负责界面展示和用户交互,例如按钮点击、数据显示等。View 通过数据绑定(Data Binding)与 ViewModel 进行通信,不直接访问 Model,也不包含业务逻辑。通过ViewModel通知来更新

  • ViewModel(视图模型):

Model 和 View 之间的桥梁,负责从 Model 中获取数据,并转换为 View 可以直接使用的形式。同时 ViewModel 处理 UI 相关逻辑,调用 Model 完成业务操作,并通过数据绑定机制通知 View 自动更新界面。

SwiftUI 项目非常适合 MVVM,因为页面是状态驱动的

优点

在 MVC 中,Controller 既要处理业务逻辑,又要操作 View 的更新。项目一复杂,Controller 就会变成几千行的"垃圾场"。

MVVM 的做法:引入 ViewModel。它只负责把 Model 的数据转换成 View 需要的格式,不直接操作 UI 控件。逻辑被极大地抽离了。
在 MVC 中,Model 变了,你通常得手动写代码去更新 View(比如 label.setText(model.name))

MVVM 的做法:通过 Data Binding(数据绑定)。只要 Model 里的数据变了,View 会自动跟着变;用户在界面改了数据,Model 也会自动更新。你再也不用写那堆繁琐的同步代码了。

  • UI 和业务逻辑分离更清晰

  • View 更轻,ViewModel 负责状态和逻辑, 不操作UI


由于 C++ 原生不支持像 JavaScript 或 swift 那样的自动监听机制,我们通常使用 观察者模式 或 回调函数 来模拟 ViewModel 对 View 的自动驱动。

cpp 复制代码
#include <iostream>
#include <string>
#include <functional>
#include <vector>

// --- 1. Model (模型) ---
// 纯粹的数据和业务逻辑
struct UserData {
    int score;
};

// --- 2. ViewModel (视图模型) ---
// 它是 View 的抽象,处理逻辑并通知 View 刷新
class CounterViewModel {
private:
    UserData model; // 持有 Model
    // 模拟数据绑定:当数据变化时执行的回调列表
    std::vector<std::function<void(const std::string&)>> scoreChangedCallbacks;

public:
    CounterViewModel() { model.score = 0; }

    // 绑定接口:View 通过这个接口注册"刷新动作"
    void bindScore(std::function<void(const std::string&)> callback) {
        scoreChangedCallbacks.push_back(callback);
    }

    // 业务逻辑:处理用户意图
    void incrementScore() {
        model.score++;
        // 核心:数据改变后,自动通知所有绑定的 View 刷新
        std::string displayStr = "当前得分: " + std::to_string(model.score);
        for (auto& cb : scoreChangedCallbacks) {
            cb(displayStr);
        }
    }
};

// --- 3. View (视图) ---
// 只负责显示和转发输入,不持有业务逻辑
class CounterView {
private:
    CounterViewModel& viewModel;

public:
    CounterView(CounterViewModel& vm) : viewModel(vm) {
        // 【数据绑定】:告诉 ViewModel,如果数据变了,就执行我的 lambda 表达式
        viewModel.bindScore([this](const std::string& uiText) {
            this->draw(uiText);
        });
    }

    // 模拟 UI 渲染
    void draw(const std::string& text) {
        std::cout << "[UI 渲染] " << text << std::endl;
    }

    // 模拟用户点击按钮
    void onButtonClick() {
        std::cout << "[UI 事件] 用户点击了增加按钮" << std::endl;
        viewModel.incrementScore();
    }
};

// --- 程序入口 ---
int main() {
    CounterViewModel vm;  // 创建逻辑层
    CounterView view(vm); // 创建表现层并完成绑定

    // 初始状态
    std::cout << "程序启动..." << std::endl;
    
    // 模拟用户两次点击
    view.onButtonClick();
    view.onButtonClick();

    return 0;
}

相关推荐
Sam_Deep_Thinking2 小时前
适合中小型企业的出口入口网关微服务
java·微服务·架构
jinanwuhuaguo2 小时前
生态融合与基座成型——OpenClaw v2026.4.24 的功能完备性跃迁与基础设施化拐点(第七篇)
人工智能·安全·架构·kotlin·openclaw
丷丩3 小时前
GeoAI Universal Platform架构重构实践:解决插件系统循环依赖,落地SDK优先架构
人工智能·架构·geoai
用户99045017780093 小时前
中小商家必看:每天刷3小时闲鱼找货源?这个工具能省下2个人力成本ai-goofish-monitor
架构
清水白石00811 小时前
Python 编程实战全景:从基础语法到插件架构、异步性能与工程最佳实践
开发语言·python·架构
ting945200012 小时前
HunyuanOCR 全方位深度解析
人工智能·架构
heimeiyingwang14 小时前
【架构实战】CQRS架构模式实战
架构
技术传感器15 小时前
Hermes为什么开始像基础设施:11万星、RCE修复与生态接入
人工智能·安全·架构·aigc
执于代码15 小时前
智能客服的agent 的架构和作用以及源码分析
架构