MVP设计模式

article/2025/9/23 3:24:21

Model–view–presenter (MVP) 是model–view–controller (MVC)设计模式派生出来的。MVP经常用来创建用户界面。
presenter是作为一个“中间人”的角色存在。在MVP中,所有页面显示逻辑都会被推送到presenter。
在这里插入图片描述
以下这张图是MVC模式的:
在这里插入图片描述
MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。

在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。
虽然 MVC 中的 View 的确“可以”访问 Model,但是我们不建议在 View 中依赖 Model,而是要求尽可能把所有业务逻辑都放在 Controller 中处理,而 View 只和 Controller 交互,将此进行改进,就有了MVP模式。

MVP是一种用户界面体系结构模式,旨在促进自动化单元测试和改进显示逻辑中关注点的分离。

  • model(模型)是定义要在用户界面中显示或以其他方式操作的数据的接口。
  • view(视图)是一个被动界面,它显示数据(模型)并将用户命令(事件)路由给presenter,以便对该数据进行操作。
  • presenter对模型和视图进行操作。它从存储库(模型)中检索数据,并格式化数据以便在视图中显示。

在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。
而且Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,即重用!

不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试–而不需要使用自动化的测试工具

我们甚至可以在Model和View都没有完成时候,就可以通过编写Mock Object(即实现了Model和View的接口,但没有具体的内容的)来测试Presenter的逻辑。

在MVP里,应用程序的逻辑主要在Presenter里实现,其中的View是很薄的一层。在这个过程中,View是很简单的,能够把信息显示清楚就可以了。

如果要实现的UI比较复杂,而且相关的显示逻辑还跟Model有关系,就可以在View和Presenter之间放置一个Adapter。由这个 Adapter来访问Model和View,避免两者之间的关联。而同时,因为Adapter实现了View的接口,从而可以保证与Presenter之间接口的不变。这样就可以保证View和Presenter之间接口的简洁,又不失去UI的灵活性。 在MVP模式里,View只应该有简单的Set/Get的方法,用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许直接访问Model——这就是与MVC很大的不同之处

通常,视图实现实例化具体的Presenter对象,并提供对自身的引用。

MVP模式的优点:

  • 模型与视图完全分离,我们可以修改视图而不影响模型
  • 所有的交互都发生在一个地方——Presenter内部,可以更高效地使用模型
  • 可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁
  • 如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)

MVP模式的缺点:

由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。还有一点需要明白,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。比如说,原本用来呈现Html的Presenter现在也需要用于呈现Pdf了,那么视图很有可能也需要变更。

MVP模式实例

Model层

IUser接口,不同的登录功能的实现类都要实现这个接口。

public interface IUser {String getUserName();String getPassword();boolean checkLogin(@NonNull String userName, @NonNull String pwd);
}

实现登录功能的实现类UserModelImpl:

public class UserModelImpl implements IUser {private String userName;private String password;public UserModelImpl(String userName,String password){this.userName = userName;this.password = password;}@Overridepublic String getUserName() {return userName;}@Overridepublic String getPassword() {return password;}@Overridepublic boolean checkLogin(@NonNull String userName, @NonNull String pwd) {if(userName.equals(this.userName) && pwd.equals(this.password)){return true;}return false;}}

如果改了登录规则,只要实现多一个实现了这个接口的登录类,然后使用它即可。要切换回去也只要用回原先那个登录类即可。

View层

ILoginView接口,所有要实现登录页的activity都要实现这个接口,只要这样,Presenter才能通过这个接口来控制视图。

public interface ILoginView {void onClearText();void onLoginResult(boolean result);
}

ILoginView接口的activity实现类LoginActivity:

package com.wong.mvpdemo.view;...public class LoginActivity extends AppCompatActivity implements ILoginView {...private ILoginPresenter loginPresenter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);...//initloginPresenter = new LoginPresenterImpl(this);}...@Overridepublic void onClearText() {editUser.setText("");editPass.setText("");}@Overridepublic void onLoginResult(boolean result) {btnLogin.setEnabled(true);btnClear.setEnabled(true);if (result) {Toast.makeText(this, "Login Success", Toast.LENGTH_SHORT).show();startActivity(new Intent(this, HomeActivity.class));} else{Toast.makeText(this, "Login Fail", Toast.LENGTH_SHORT).show();}}}

presenter层

这一层实现了Model与View层的解耦,所有的业务逻辑都在这一层实现。
ILoginPresenter接口,所有的登录页Activity内部都要声明这个接口,这样登录页Activity才能通过这个接口来实现业务逻辑。因此ILoginPresenter的初始化是在Activity中完成的。

public interface ILoginPresenter {void clear();void doLogin(String name, String password);
}

实现ILoginPresenter接口:

package com.wong.mvpdemo.presenter;import android.os.Handler;
import android.os.Looper;import com.wong.mvpdemo.model.IUser;
import com.wong.mvpdemo.model.UserModelImpl;
import com.wong.mvpdemo.view.ILoginView;/*** @author WongKyunban* description* created at 2019-04-10 下午7:13* @version 1.0*/
public class LoginPresenterImpl implements ILoginPresenter {private ILoginView iLoginView; //视图private IUser user; //模型private Handler handler;public LoginPresenterImpl(ILoginView iLoginView) {this.iLoginView = iLoginView;initUser();handler = new Handler(Looper.getMainLooper());}@Overridepublic void clear() {iLoginView.onClearText();}@Overridepublic void doLogin(String name, String password) {final boolean isSuccess = user.checkLogin(name, password);handler.postDelayed(new Runnable() {@Overridepublic void run() {iLoginView.onLoginResult(isSuccess);}}, 3000);}private void initUser() {user = new UserModelImpl("wongkyunban", "1688");}}

presenter结合model模型来实现业务逻辑,通过view层来控制视图。所以model中的业务接口与presenter的接口要大概一致,因为说到底presenter是要通过model来完成业务的。view的接口,则要看业务的结果需要更新那些UI来定。

demo示例


http://chatgpt.dhexx.cn/article/i0Hp8t4u.shtml

相关文章

Android中用到的MVP模式

参考:android架构设计—mvp模式封装 很简单,M:数据, V:界面, P:一个使唤数据(M)和界面(V)干活的大管家。 特点:在P的管理下,P可以直接支配V和M做一些事情。但是V,与M,你…

Android MVP模式 简单易懂的介绍方式

Android MVP Pattern Android MVP 模式1 也不是什么新鲜的东西了,我在自己的项目里也普遍地使用了这个设计模式。当项目越来越庞大、复杂,参与的研发人员越来越多的时候,MVP 模式的优势就充分显示出来了。 导读:MVP模式是MVC模式在…

Android MVP模式详解

一、MVP概述 MVP,全称 Model-View-Presenter,即模型-视图-层现器。 提到MVP,就必须要先介绍一下它的前辈MVC,因为MVP正是基于MVC的基础发展而来的。两个之间的关系也是源远流长。 MVC,全称Model-View-Controller&am…

浅谈安卓MVP模式

本篇博文通过对google官方demo:https://github.com/googlesamples/android-architecture/tree/todo-mvp/的理解,用自己的demo更好的讲解mvp的概念,帮助大家如何针对一个Activity页面去编写针对MVP风格的代码。 一、MVP模式介绍 随着UI创建技…

简单易懂 MVP 模式

Android MVP 模式 [1] 也不是什么新鲜的东西了,我在自己的项目里也普遍地使用了这个设计模式。当项目越来越庞大、复杂,参与的研发人员越来越多的时候,MVP 模式 的优势就充分显示出来了。 MVP 模式是 MVC 模式在 Android 上的一种变体&#…

深入浅出——MVP模式

由于公司里的架构模式用到MVP,觉得自己还不够熟悉,决定在此理一理,并给大家一起总结下。 一 MVP模式介绍 MVP全称Model View Presenter。 MVP能够有效的降低View的复杂性,避免业务逻辑被塞进View中,防止View的代码变…

MVP模式简单讲解,通俗易懂

了解 MVP 和 MVC 的区别 https://baike.baidu.com/item/MVP/3714550?fraladdin 什么是MVP: MVP 是 MVC 的变种,其实是一种升级。要说 MVP 就要说说 MVC,在 MVC 中 Activity 其实是 View层级,但是通常在使用中 Activity即是View…

MVP框架模式

一、基本概念 MVP是Model-View-Presenter的简称,即模型-视图-表现层的缩写。MVP是由MVC模式进化而来的,MVP改进了MVC中的控制器过于臃肿的问题。 与MVC一样,MVP将应用程序的数据处理、数据显示和逻辑控制分开,用一种业务逻辑、数…

分析几个面试题:==和===;绑定事件;正则表达式

今天也是我学后端的朋友给我发了三个前端的面试题,这里我们试着分析一波。 目录 1、和的含义是什么,又有什么区别呢? (1)赋值: (2)相同: (3)…

前端面经总结

HTML及浏览器 对栅栏布局的理解 栅格化布局中的元素:column列,row行,gutter列之间的距离,container容器 栅格是否可以嵌套 canvas和svg的区别 SVG: SVG 是一种使用 XML 描述 2D 图形的语言。 在 SVG 中,…

前端深入学习

但是面试中必考的点且占比非常大的有前端基础和算法。 决定你是否能拿sp offer(高薪offer)以及是否进名企的是项目和算法。 absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。 元素的位置通过 “left”, “to…

web前端常用词汇

html中的单词 Network [netwɜːk] 网络 General [dʒen(ə)r(ə)l] 一般的,大体的 Request [rɪkwest] 请求 Response [rɪspɒns] 响应 Headers [hedəz] 标题 HyperText [haɪpətekst] 超文本 Transfer [trnsfɝ] 传递 Protocol [prəʊtə…

前端html、css、JavaScript---硬核知识汇总

前端HTML篇 硬核!一篇文章教你阅遍html。 声明:本篇文章只是一个刚开始学习后端开发的菜鸟汇总完成的 JavaWeb学习前导html篇,所以专业性肯定不如前端人员,但用于学习后端开发足够了,刚接触html的童鞋拿来快速了解ht…

前端面试题总结(转载)

DOM结构 —— 两个节点之间可能存在哪些关系以及如何在节点之间任意移动1.DOM中两个节点存在的关系无非3种:1.1.包含与被包含,IE率先引入的contains()方法可检测,例 A.contains(B),即检查节点B是否是节点A的子节点,返回布尔值&…

前端三件套知识点

html 常用插件 文件比较 常用快捷键 ctrl f 查找当前页面的内容 !后按table 或者 html:5 代码模板快捷键 altb调试快捷键 ctrlk ctrlt改颜色主题 altshifta注释快捷键 html基础概念 一、 WEB标准的概念及组成 WEB标准不是某一个标准,而是一系列标准的集合。 …

php前端搜索功能,JavaScript实现前端实时搜索功能的代码分享(图)

这篇文章主要为大家详细介绍了JavaScript实现前端实时搜索功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 大部分页面都具备搜索功能。而作为前端,我们的目的只是将用户输入的内容返回给后台而后呈现反馈数据给用户,具体实…

前端实时搜索功能

** 大部分页面都具备搜索功能。而作为前端&#xff0c;我们的目的只是将用户输入的内容返回给后台而后呈现反馈数据给用户&#xff0c;具体实现如下&#xff1a; ** 1.基本布局&#xff1a; <div class"searcher"><p class"searcher-main">…

适合后端开发人员的html笔记

1html 锚点 <a href"#bottom">跳转到底部</a> <div class"aa"></div> <a href"#" id"bottom">跳转到顶部</a> img 图片标签 h1:一级标题块级元素其他的都是行内元素 img同时具备行内元素和块级…

【JavaScript】 一万字 JavaScript 笔记(详细讲解 + 代码演示 + 图解)

文章目录 变量 变量声明的提升数据类型Typeof运算符数据类型转换 表达式与运算符 隐式类型转换toFixed(a)方法保留a位小数关系运算符短路求值流程控制语句 数组函数DOMBOM面向对象 变量 一个变量只定义但没有赋初值&#xff0c;默认值是 undefined定义变量时必须写var&a…

前端面试 汇总整理

-----------------------------------------html css-------------------------------------------- 一.回流与重绘 回流一定引起重绘&#xff0c;重绘不一定回流 1.浏览器渲染机制 1&#xff09;浏览器采用流式布局。 2&#xff09;浏览器将html解析成DOM&#xff0c;css解析成…