当前位置: 首页 > article >正文

系统架构:MVVM

引言

MVVM 全称 Model-View-ViewModel,是在 MVP(Model-View-Presenter)架构模式基础上的进一步演进与优化。MVVM 与 MVP 的基本架构相似,但 MVVM 独特地引入了数据双向绑定机制。这一创新机制有效解决了 MVP 模式中 Model 与 View 之间存在的耦合问题,极大地简化了两者间的映射关系以及繁琐的 DOM 操作流程。MVVM 架构模式致力于助力开发者更高效地分离用户界面(UI)与复杂的业务逻辑,进而显著提升代码的可维护性与可扩展性。

MVVM架构范式最初由微软架构师Ken Cooper和Ted Peters提出,并在Windows Presentation Foundation(WPF)平台上成功实施。由另外一位微软架构师 John Gossman在其博客《Introduction to Model/View/ViewModel pattern for building WPF apps》中发布。

MVVM的组件

MVVM 主要由 Model、View、ViewModel 和 DataBinding 四个核心组件构成,其架构关系图示如下:
在这里插入图片描述

View

View组件即用户界面(User Interface),在MVVM架构中,View只包含一层很薄的展示逻辑。View通过数据绑定(DataBinding)与ViewModel进行交互。当View与ViewModel完成数据绑定后,View中的任何变化都会自动反馈到ViewModel中,而View则无法直接感知Model的存在。这种设计使得View更加专注于展示,而不需要处理复杂的业务逻辑。

Model

Model组件与MVP架构中的Model类似,负责数据的存储和管理。Model层提供数据更新接口供ViewModel调用,以实现数据的更新。当Model中的数据发生变化时,会通过通知机制(如Notify)告知ViewModel,以便ViewModel进行相应的处理。

ViewModel

ViewModel组件位于View和Model之间,负责将Model的数据转换成View可以感知的形式。ViewModel通过数据绑定(DataBinding)将数据与View进行绑定,使得数据的变化能够自动更新到View上,从而实现数据的双向绑定。此外,ViewModel还通常包含用户的交互逻辑,如处理按钮点击等事件。

DataBinding

数据绑定(DataBinding)是MVVM架构中实现View和ViewModel之间数据双向流动更新的核心机制。在MVC或MVP架构中,View的更新和响应需要开发者编写大量复杂且冗余的代码。而在MVVM架构中,由于数据绑定的存在,开发者无需编写这部分复杂的代码,可以将更多的精力投入到核心业务功能的开发上。

MVVM实现

MVVM 涵盖 View、ViewModel、Model、DataBinding 四个核心模块。一般而言,View 对应相应页面布局的 xml 文件;ViewModel 对应业务逻辑的实现;DataBinding 负责建立页面布局文件与 ViewModel 业务实现之间的绑定关系。在 Android 开发环境中,由于存在原生 DataBinding 库,我们往往难以一窥 DataBinding 实现的全貌。鉴于 C++ 本身缺乏类似 Android 的原生 DataBinding 库,此处我们依据 DataBinding 的观察者实现原理,编写一个 C++ 版本的用户登录 MVVM 示例,以此助力大家深入透彻地理解 MVVM 实现的精髓。

Observer接口

#include <vector>
#include <string>

class Observer
{
public:
    virtual void onChanged(const std::string& fieldName) = 0;
    virtual ~Observer() = default;
};

ObservableField 类

ObservableField 类是数据绑定的核心要素,承担着存储数据以及在数据变更时通知所有观察者的关键职责。

template <typename T>
class ObservableField
{
public:
    explicit ObservableField(const std::string& fieldName, T value)
    : m_fieldName(fieldName)
    , m_value(std::move(value))
    {
    }

    void set(T value)
    {
        if (m_value != value)
        {
            m_value = std::move(value);
            notifyObservers();
        }
    }

    const T& get() const
    {
        return m_value;
    }

    void addObserver(Observer* observer)
    {
        m_observers.push_back(observer);
    }

private:
    void notifyObservers()
    {
        for (auto observer : m_observers)
        {
            if (observer)
            {
                observer->onChanged(m_fieldName);
            }
        }
    }

    std::string m_fieldName;
    T m_value;
    std::vector<Observer*> m_observers;
};

Model 类

UserModel 类用于验证用户名和密码。

#include <string>

class UserModel
{
public:
    UserModel(std::string correctUsername, std::string correctPassword)
    : m_correctUsername(std::move(correctUsername))
    , m_correctPassword(std::move(correctPassword))
    {
    }

    bool validateLogin(const std::string& username, const std::string& password) const
    {
        return username == m_correctUsername && password == m_correctPassword;
    }

private:
    std::string m_correctUsername;
    std::string m_correctPassword;
};

ViewModel 类

ViewModel 是 MVVM 模式的核心枢纽,它有效分离了业务逻辑与视图。ViewModel 负责从 Model 获取数据,处理用户输入,并通过 ObservableField 通知视图更新。

class View; // 前向声明

class ViewModel : public Observer
{
public:
    ViewModel(UserModel* model)
    : m_model(model)
    , m_view(nullptr)
    , m_usernameField("username", "")
    , m_passwordField("password", "")
    {
        m_usernameField.addObserver(this);
        m_passwordField.addObserver(this);
    }

    void setView(View* view)
    {
        m_view = view;
    }

    void setUsername(const std::string& username)
    {
        m_usernameField.set(username);
    }

    void setPassword(const std::string& password)
    {
        m_passwordField.set(password);
    }

    void login()
    {
        if (m_model->validateLogin(m_usernameField.get(), m_passwordField.get()))
        {
            std::cout << "Login successful!" << std::endl;
        }
        else
        {
            std::cout << "Login failed! Incorrect username or password." << std::endl;
        }
    }

    void onChanged(const std::string& fieldName) override
	{
	    if (m_view)
	    {
	        m_view->updateField(fieldName);
	    }
	}

    const std::string& getUsername() const
    {
        return m_usernameField.get();
    }

    const std::string& getPassword() const
    {
        return m_passwordField.get();
    }

private:
    UserModel* m_model;
    View* m_view;

    ObservableField<std::string> m_usernameField;
    ObservableField<std::string> m_passwordField;
};

View 类

View 类负责与用户进行交互,接收用户输入并传递给 ViewModel,同时负责更新 UI 界面。

class View
{
public:
    explicit View(ViewModel* viewModel)
    : m_viewModel(viewModel)
    {
    }

    void simulateUserInput()
    {
        std::string username, password;

        std::cout << "Enter username: ";
        std::getline(std::cin, username);
        m_viewModel->setUsername(username);

        std::cout << "Enter password: ";
        std::getline(std::cin, password);
        m_viewModel->setPassword(password);

        m_viewModel->login();
    }

    void updateField(const std::string& fieldName)
    {
        if (fieldName == "username")
        {
            std::cout << "Updated Username: " << m_viewModel->getUsername() << std::endl;
        }
        else if (fieldName == "password")
        {
            std::cout << "Updated Password: " << m_viewModel->getPassword() << std::endl;
        }
    }

private:
    ViewModel* m_viewModel;
};

主程序 (Main)

在 main 函数中,我们创建 UserModel、ViewModel 和 View 实例,并模拟用户输入来验证登录。


int main() 
{
    UserModel userModel("user", "password");
    ViewModel viewModel(&userModel);
    View view(&viewModel);

    viewModel.setView(&view);

    view.simulateUserInput();
}

如果用户输入正确的用户名和密码,程序输出如下:

Enter username: user
Updated Username: user
Enter password: password
Updated Password: password
Login successful!

如果用户输入错误的用户名或密码,程序输出如下:

Enter username: a
Updated Username: a
Enter password: b
Updated Password: b
Login failed! Incorrect username or password.

总结

MVVM 架构模式作为一种先进的软件设计模式,通过引入数据双向绑定机制,成功地在 Model、View 和 ViewModel 之间构建起高效的协同工作体系。在该架构中,View 专注于展示,Model 专注于数据管理,ViewModel 则作为桥梁,负责数据转换与交互逻辑处理,DataBinding 确保了数据的自动双向流动。这种职责分离的设计极大地提高了代码的可维护性与可扩展性,降低了各组件之间的耦合度。本文通过 C++ 实现的用户登录示例,深入剖析了 MVVM 的各个组件及其实现原理,展示了 MVVM 在实际应用中的工作流程。无论是对于前端开发还是后端开发,理解和掌握 MVVM 架构模式都有助于提升软件开发的质量与效率,为构建复杂而稳定的应用程序奠定坚实的基础。


http://www.kler.cn/a/418344.html

相关文章:

  • 基于DHCP,ACL的通信
  • 探索温度计的数字化设计:一个可视化温度数据的Web图表案例
  • Paper -- 建筑物高度估计 -- 基于深度学习、图像处理和自动地理空间分析的街景图像建筑高度估算
  • GoogleTest做单元测试
  • 亚马逊API拿取商品详情
  • springboot359智慧草莓基地管理系统(论文+源码)_kaic
  • YOLOv8-ultralytics-8.2.103部分代码阅读笔记-files.py
  • LSTM神经网络时间序列
  • 使用Docker在Ubuntu 22.04上部署MySQL数据库的完整指南
  • 如何在 VPS 上设置 Apache 并使用免费签名的 SSL 证书
  • Uniapp 使用自定义字体
  • Linux下如何安装JDK
  • 粒子群算法优化RBF网络
  • spark同步mysql数据到sqlserver
  • Latex相关问题
  • 基于yolov8、yolov5的铝材缺陷检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
  • 强国复兴项目携手易方达基金、广发基金 高效推进扶贫金发放与保障房建设
  • windows C#-相等比较
  • 《windows堆内存剖析(一)》
  • ChromeBook11 HP G7EE 刷入Ubuntu的记录
  • 鲲鹏麒麟安装离线版MySQL5.7
  • 吉客云数据集成技巧:智能实现MySQL物料信息查询
  • 栈-数组描述(C++)
  • mysql查询语句执行全流程
  • 10x 性能提升,ProtonBase 为教育行业提供统一的数据库和数仓体验
  • 【C#设计模式(16)——解释器模式(Interpreter Pattern)】