C# 中的 MVC、MVP、MVVM 模式详解

这三种都是分层架构设计模式,核心目标是解耦代码、提高可维护性和可测试性,在 C# 开发(尤其是桌面 / Web 应用)中应用广泛。下面从「定义 + 核心角色 + C# 示例 + 适用场景」逐一讲解。


一、MVC(Model-View-Controller)

1. 核心概念

  • Model:数据模型(业务逻辑、数据实体),不依赖任何层。
  • View:视图(UI 界面),展示数据,接收用户输入,依赖 Model。
  • Controller:控制器,处理用户请求,协调 Model 和 View(比如接收 View 的输入,调用 Model 处理数据,再更新 View)。
  • 核心流程:用户操作 → Controller 接收 → 调用 Model 处理数据 → Controller 传递数据给 View → View 展示。
  • 特点:View 和 Controller 双向交互,Controller 直接控制 View 的更新。

2. C# MVC 简单示例(ASP.NET MVC 场景)

复制代码
// 1. Model(数据模型)
public class UserModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    // 模拟业务逻辑
    public UserModel GetUserById(int id)
    {
        return new UserModel { Id = id, Name = "张三" };
    }
}

// 2. Controller(控制器,ASP.NET MVC 中继承 Controller 基类)
public class UserController : Controller
{
    // 处理用户请求(比如访问 /User/Detail/1)
    public ActionResult Detail(int id)
    {
        // 调用 Model 获取数据
        var userModel = new UserModel();
        var user = userModel.GetUserById(id);
        // 将数据传递给 View
        return View(user);
    }
}

// 3. View(视图,Razor 页面 /Views/User/Detail.cshtml)
@model UserModel
<h1>用户详情</h1>
<p>ID:@Model.Id</p>
<p>姓名:@Model.Name</p>

3. 适用场景

  • ASP.NET MVC(Web 应用)、WinForm 基础场景。
  • 适合简单应用,开发速度快,但 View 和 Controller 耦合度略高。

二、MVP(Model-View-Presenter)

1. 核心概念

MVC 的改进版,核心是解耦 View 和 Model,引入 Presenter 作为中间层:

  • Model:和 MVC 一致(数据 / 业务逻辑)。
  • View :纯展示层,不包含任何业务逻辑,仅暴露接口给 Presenter 调用(比如 ShowUser(UserModel))。
  • Presenter:主持人,持有 View 和 Model 的引用,处理所有业务逻辑,是核心层(View 的输入交给 Presenter,Presenter 调用 Model 后,通过 View 接口更新界面)。
  • 核心流程:用户操作 → View 通知 Presenter → Presenter 调用 Model → Presenter 通过 View 接口更新 View。
  • 特点:View 完全被动,Presenter 主导,View 和 Model 完全解耦,可测试性更强。

2. C# MVP 简单示例(WinForm 场景)

复制代码
// 1. Model
public class UserModel
{
    public int Id { get; set; }
    public string Name { get; set; }

    public UserModel GetUser(int id)
    {
        return new UserModel { Id = id, Name = "李四" };
    }
}

// 2. View 接口(解耦 Presenter 和具体 View)
public interface IUserView
{
    int UserId { get; set; } // 接收用户输入的 ID
    void ShowUserInfo(string name); // 展示用户名称
}

// 3. Presenter
public class UserPresenter
{
    private readonly IUserView _view;
    private readonly UserModel _model;

    public UserPresenter(IUserView view)
    {
        _view = view;
        _model = new UserModel();
    }

    // 处理「查询用户」逻辑
    public void LoadUser()
    {
        var user = _model.GetUser(_view.UserId);
        _view.ShowUserInfo(user.Name); // 通过接口更新 View
    }
}

// 4. 具体 View(WinForm 窗体)
public partial class UserForm : Form, IUserView
{
    private readonly UserPresenter _presenter;

    public UserForm()
    {
        InitializeComponent();
        _presenter = new UserPresenter(this);
        // 按钮点击事件绑定
        btnQuery.Click += (s, e) => _presenter.LoadUser();
    }

    // 实现 IUserView 接口
    public int UserId
    {
        get => int.Parse(txtId.Text);
        set => txtId.Text = value.ToString();
    }

    public void ShowUserInfo(string name)
    {
        lblName.Text = name; // 更新界面控件
    }
}

3. 适用场景

  • WinForm/WPF 桌面应用(早期)、对测试性要求较高的中小型应用。
  • 缺点:Presenter 可能会变得臃肿(需手动处理大量 View 接口)。

三、MVVM(Model-View-ViewModel)

1. 核心概念

MVP 的进阶版,核心是数据绑定(Data Binding),消除 Presenter 手动更新 View 的冗余代码:

  • Model:和前两者一致(数据 / 业务逻辑)。
  • View :视图(UI),通过数据绑定和 ViewModel 关联,无需手动更新,支持双向绑定(View 输入自动同步到 ViewModel,ViewModel 数据变化自动更新 View)。
  • ViewModel :视图模型,封装 View 的逻辑和数据,实现 INotifyPropertyChanged(通知 View 数据变化),是 View 的「抽象」,不依赖具体 View。
  • 核心流程:用户操作 → View 绑定的 ViewModel 接收数据 → ViewModel 调用 Model → ViewModel 触发属性变更通知 → View 自动更新。
  • 特点:数据驱动,无需手动更新 View,View 和 ViewModel 解耦,可测试性最高。

2. C# MVVM 简单示例(WPF 场景)

复制代码
// 1. 基础类:实现属性变更通知(MVVM 核心)
public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

// 2. Model
public class UserModel
{
    public int Id { get; set; }
    public string Name { get; set; }

    public UserModel GetUser(int id)
    {
        return new UserModel { Id = id, Name = "王五" };
    }
}

// 3. ViewModel
public class UserViewModel : ObservableObject
{
    private readonly UserModel _model;
    private int _userId;
    private string _userName;

    // 绑定到 View 的属性(用户输入的 ID)
    public int UserId
    {
        get => _userId;
        set
        {
            _userId = value;
            OnPropertyChanged(); // 通知 View 数据变化
        }
    }

    // 绑定到 View 的属性(展示的用户名)
    public string UserName
    {
        get => _userName;
        set
        {
            _userName = value;
            OnPropertyChanged(); // 通知 View 数据变化
        }
    }

    // 绑定到 View 按钮的命令
    public ICommand LoadUserCommand { get; }

    public UserViewModel()
    {
        _model = new UserModel();
        // 初始化命令(RelayCommand 是 WPF 中常用的命令实现)
        LoadUserCommand = new RelayCommand(LoadUser);
    }

    private void LoadUser()
    {
        var user = _model.GetUser(UserId);
        UserName = user.Name; // 自动通知 View 更新
    }
}

// 辅助:RelayCommand 实现(WPF 命令接口)
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    public event EventHandler? CanExecuteChanged;

    public RelayCommand(Action execute) => _execute = execute;
    public bool CanExecute(object? parameter) => true;
    public void Execute(object? parameter) => _execute();
}

// 4. View(WPF XAML,数据绑定)
<Window x:Class="MVVMDemo.UserWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:MVVMDemo"
        Title="用户查询" Height="200" Width="300">
    <!-- 设置 DataContext 为 ViewModel -->
    <Window.DataContext>
        <vm:UserViewModel />
    </Window.DataContext>

    <StackPanel Margin="20">
        <!-- 双向绑定 UserId:View 输入同步到 ViewModel -->
        <TextBox Text="{Binding UserId, Mode=TwoWay}" PlaceholderText="输入用户ID"/>
        <!-- 绑定命令:点击按钮触发 ViewModel 的 LoadUser 方法 -->
        <Button Content="查询" Command="{Binding LoadUserCommand}" Margin="0,10"/>
        <!-- 绑定 UserName:ViewModel 变化自动更新 View -->
        <TextBlock Text="{Binding UserName}" FontSize="16"/>
    </StackPanel>
</Window>

3. 适用场景

  • WPF/MAUI/Blazor(现代 C# 界面框架)、复杂交互的桌面 / 跨平台应用。
  • 优点:数据驱动,代码量少,可测试性和可维护性最优;缺点:学习成本略高(需理解数据绑定、命令等概念)。

四、三者核心对比

特性 MVC MVP MVVM
核心解耦 View-Controller 耦合 View-Presenter 接口解耦 View-ViewModel 数据绑定解耦
交互方式 Controller 直接更新 View Presenter 调用 View 接口 数据绑定自动更新
测试性 中等 较高 最高
适用框架 ASP.NET MVC WinForm(早期) WPF/MAUI/Blazor
代码冗余 中(手动写接口) 少(数据绑定)

总结

  1. MVC :最基础,Controller 主导,适合简单 Web 应用(如 ASP.NET MVC),开发快但耦合略高。
  2. MVP:解耦 View 和 Model,Presenter 手动控制 View,适合早期桌面应用,测试性优于 MVC。
  3. MVVM:数据驱动核心,依赖数据绑定,是现代 C# 界面开发(WPF/MAUI)的首选,解耦和可维护性最优。

核心选择原则:简单 Web 用 MVC,现代桌面 / 跨平台用 MVVM,MVP 仅作为过渡或老项目维护场景使用。

相关推荐
春日见2 小时前
Matlab快速入门 基础语法教学
java·开发语言·驱动开发·matlab·docker·计算机外设
dgfhf2 小时前
高性能计算资源调度
开发语言·c++·算法
Lhan.zzZ2 小时前
Qt绘图探秘:如何避免多QPainter冲突引发的程序崩溃
开发语言·c++·qt
晨曦_子画2 小时前
C# sql语句含有 like %name%如何提高查询效率
数据库·sql·c#
Ralph_Y2 小时前
C++:迭代器失效
开发语言·c++
smart margin2 小时前
Python安装教程
开发语言·python
weixin_307779132 小时前
OpenClaw-CN 安全增强方案:从理念到落地的全面剖析
开发语言·人工智能·算法·安全·语言模型
new code Boy2 小时前
前端核心基础汇总
开发语言·javascript·原型模式
ou.cs2 小时前
C# params 关键字详解:从入门到精通(保姆级教程)
开发语言·c#·.net