MVVM、MVC、MVP 的区别

news/2024/12/23 22:13:00 标签: mvc, mvp, mvvm, windows

MVVM(Model-View-ViewModel)、MVC(Model-View-Controller)和MVP(Model-View-Presenter)是三种常见的软件架构模式,它们在客户端应用开发中被广泛使用。每种模式都有其特定的设计理念和应用场景,下面将详细介绍这三种模式的区别,并通过示例来说明。

1. MVC (Model-View-Controller)

核心思想

  • Model:负责数据的存储和业务逻辑。
  • View:负责展示数据,用户界面。
  • Controller:负责处理用户输入,更新模型和视图。

工作流程

  1. 用户与视图进行交互。
  2. 视图将用户的输入传递给控制器。
  3. 控制器根据输入调用模型的方法,更新模型的状态。
  4. 控制器通知视图更新以反映模型的变化。

优点

  • 分离关注点,使得代码结构清晰。
  • 便于维护和扩展。

缺点

  • 对于复杂的UI,控制器可能会变得臃肿。
  • 视图和控制器之间的耦合较高。

示例: 假设我们有一个简单的待办事项应用:

// Model
class TodoModel {
  constructor() {
    this.todos = [];
  }

  addTodo(todo) {
    this.todos.push(todo);
  }

  removeTodo(index) {
    this.todos.splice(index, 1);
  }
}

// View
class TodoView {
  constructor(model, controller) {
    this.model = model;
    this.controller = controller;
    this.init();
  }

  init() {
    const addButton = document.getElementById('addButton');
    addButton.addEventListener('click', () => {
      const input = document.getElementById('todoInput');
      this.controller.addTodo(input.value);
      input.value = '';
    });

    const list = document.getElementById('todoList');
    this.model.todos.forEach((todo, index) => {
      const li = document.createElement('li');
      li.textContent = todo;
      const removeButton = document.createElement('button');
      removeButton.textContent = '删除';
      removeButton.addEventListener('click', () => {
        this.controller.removeTodo(index);
      });
      li.appendChild(removeButton);
      list.appendChild(li);
    });
  }

  update() {
    const list = document.getElementById('todoList');
    list.innerHTML = '';
    this.model.todos.forEach((todo, index) => {
      const li = document.createElement('li');
      li.textContent = todo;
      const removeButton = document.createElement('button');
      removeButton.textContent = '删除';
      removeButton.addEventListener('click', () => {
        this.controller.removeTodo(index);
      });
      li.appendChild(removeButton);
      list.appendChild(li);
    });
  }
}

// Controller
class TodoController {
  constructor(model, view) {
    this.model = model;
    this.view = view;
  }

  addTodo(todo) {
    this.model.addTodo(todo);
    this.view.update();
  }

  removeTodo(index) {
    this.model.removeTodo(index);
    this.view.update();
  }
}

const model = new TodoModel();
const view = new TodoView(model);
const controller = new TodoController(model, view);

2. MVP (Model-View-Presenter)

核心思想

  • Model:负责数据的存储和业务逻辑。
  • View:负责展示数据,用户界面。
  • Presenter:作为中间层,处理用户输入,更新模型,并控制视图的显示。

工作流程

  1. 用户与视图进行交互。
  2. 视图将用户的输入传递给Presenter。
  3. Presenter根据输入调用模型的方法,更新模型的状态。
  4. Presenter更新视图以反映模型的变化。

优点

  • 分离了视图和业务逻辑。
  • 测试更加容易。

缺点

  • Presenter可能变得复杂。
  • 视图和Presenter之间的接口需要仔细设计。

示例: 继续上面的待办事项应用,但这次使用MVP模式:

// Model
class TodoModel {
  constructor() {
    this.todos = [];
  }

  addTodo(todo) {
    this.todos.push(todo);
  }

  removeTodo(index) {
    this.todos.splice(index, 1);
  }

  getTodos() {
    return this.todos;
  }
}

// View
class TodoView {
  constructor(presenter) {
    this.presenter = presenter;
    this.init();
  }

  init() {
    const addButton = document.getElementById('addButton');
    addButton.addEventListener('click', () => {
      const input = document.getElementById('todoInput');
      this.presenter.addTodo(input.value);
      input.value = '';
    });

    const list = document.getElementById('todoList');
    this.renderTodos(this.presenter.getTodos());
  }

  renderTodos(todos) {
    const list = document.getElementById('todoList');
    list.innerHTML = '';
    todos.forEach((todo, index) => {
      const li = document.createElement('li');
      li.textContent = todo;
      const removeButton = document.createElement('button');
      removeButton.textContent = '删除';
      removeButton.addEventListener('click', () => {
        this.presenter.removeTodo(index);
      });
      li.appendChild(removeButton);
      list.appendChild(li);
    });
  }
}

// Presenter
class TodoPresenter {
  constructor(view, model) {
    this.view = view;
    this.model = model;
  }

  addTodo(todo) {
    this.model.addTodo(todo);
    this.view.renderTodos(this.model.getTodos());
  }

  removeTodo(index) {
    this.model.removeTodo(index);
    this.view.renderTodos(this.model.getTodos());
  }

  getTodos() {
    return this.model.getTodos();
  }
}

const model = new TodoModel();
const view = new TodoView();
const presenter = new TodoPresenter(view, model);
view.presenter = presenter;

3. MVVM (Model-View-ViewModel)

核心思想

  • Model:负责数据的存储和业务逻辑。
  • View:负责展示数据,用户界面。
  • ViewModel:作为中介者,负责数据绑定、命令处理和状态管理。

工作流程

  1. 用户与视图进行交互。
  2. ViewModel监听视图的变化,并更新模型。
  3. ViewModel监听模型的变化,并更新视图。

优点

  • 数据绑定机制简化了视图和模型之间的同步。
  • 降低了视图和模型之间的耦合。

缺点

  • 可能会增加内存开销。
  • 复杂的数据绑定逻辑可能难以调试。

示例: 继续上面的待办事项应用,但这次使用MVVM模式(使用Vue.js实现):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue MVVM示例</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@next"></script>
</head>
<body>
  <div id="app">
    <h1>待办事项</h1>
    <input v-model="newTodo" placeholder="添加新事项" @keyup.enter="addTodo">
    <ul>
      <li v-for="(todo, index) in todos" :key="index">
        {{ todo }}
        <button @click="removeTodo(index)">删除</button>
      </li>
    </ul>
  </div>

  <script>
    const app = Vue.createApp({
      data() {
        return {
          newTodo: '',
          todos: []
        };
      },
      methods: {
        addTodo() {
          if (this.newTodo.trim()) {
            this.todos.push(this.newTodo);
            this.newTodo = '';
          }
        },
        removeTodo(index) {
          this.todos.splice(index, 1);
        }
      }
    });

    app.mount('#app');
  </script>
</body>
</html>

总结

  • MVC:适用于传统的Web应用,尤其是服务器端渲染的应用。它通过控制器协调模型和视图之间的交互。
  • MVP:适用于需要高度测试性的应用,特别是移动应用。它通过Presenter来分离视图和业务逻辑。
  • MVVM:适用于现代的单页应用(SPA),特别是使用JavaScript框架如Vue、Angular或React构建的应用。它通过数据绑定简化了视图和模型之间的同步。

选择哪种模式取决于具体的应用场景和需求。MVVM由于其简洁的数据绑定机制,在现代前端开发中非常流行。


http://www.niftyadmin.cn/n/5797060.html

相关文章

CS 144 check5: down the stack (the network interface)

Lectures Note 略 Exercises TCP片段传输到对等方的过程&#xff1a; TCP-in-UDP-in-IP. Linux 提供了一种接口&#xff08;即“数据报套接字”&#xff0c;UDPSocket&#xff09;&#xff0c;它允许应用程序仅提供用户数据报的有效载荷和目标地址&#xff0c;而内核则负责…

AI的使用:初见

一、AI初见 二、AI基础 生成式人工智能、大语言模型、提示词 三、提示词-Prompt 你糊弄AI&#xff0c;AI也糊弄你。 与AI交流&#xff0c;和与人交流一样。对AI要准确的表达出你的意思。就像我们给领导汇报工作一样&#xff0c;要使用很多科学的思维模型&#xff0c;比如S…

【C++ 真题】P1031 [NOIP2002 提高组] 均分纸牌

[NOIP2002 提高组] 均分纸牌 题目描述 有 N N N 堆纸牌&#xff0c;编号分别为 1 , 2 , … , N 1,2,\ldots,N 1,2,…,N。每堆上有若干张&#xff0c;但纸牌总数必为 N N N 的倍数。可以在任一堆上取若干张纸牌&#xff0c;然后移动。 移牌规则为&#xff1a;在编号为 1 …

2. Kafka入门-开发环境准备

Kafka入门-开发环境准备 1. 环境准备---------------------------------------------------------------------------------------------- 1. 环境准备 ----------------------------------------------------------------------------------------------

架构演进之路

架构演进 前言1. 单机架构2. 应用数据分离架构3. 应用服务集群架构4. 读写分离 / 主从分离5. 冷热分离架构6. 业务拆分 —— 微服务7. 总结 前言 架构之所以会进行演变&#xff0c;是因为硬件的限制导致没办法容纳更多的请求 解决方法一般有&#xff1a;开源、节流 开源&#…

基于SpringBoot的仿掘金个人博客系统(2025最新原创)

系统介绍&#xff1a;仿掘金精美博客系统 一、概述 本博客系统是一款仿掘金设计的精美博客平台&#xff0c;旨在为用户提供一个功能丰富、操作简便的博客管理环境。系统采用现代化的技术栈&#xff0c;确保了高性能、高可用性和良好的用户体验。 源码资料&#xff1a; http:…

Golang 的并发优势

在如今的编程领域&#xff0c;一个程序能够同时处理多个任务的能力非常重要&#xff0c;这就是所谓的并发处理。而 Golang 在并发编程方面表现十分出色&#xff0c;具有很多独特的优势&#xff0c;简直不要太简单。 一、轻量级的协程&#xff08;Goroutine&#xff09; 在传统…

详细分析:AG32 MCU与STM32/GD32的区别

一、MCU内核的区别 STM32/GD32是ARM Cortex内核; AG32是目前最新的RISC-V内核,该内核具有速率高,功耗低等特点,不受制于ARM,应用灵活等特点。 二、AG32与STM32/GD32 MCU的引脚区别 AG32 芯片和其他芯片(比如ST、GD)在使用上有一个很大的差异点,是AG32 的IO 引脚并不…