MVP模式分析
来源:互联网 发布:英语作文人工智能 编辑:程序博客网 时间:2024/05/19 03:43
MVP模式分析
一、为什么使用MVP模式
这个问题我们就得首先从MVC说起了,我们知道MVC曾是我们熟悉的设计框架模式,但是正是MVC设计中存在弊端,所以才使我们程序员追求更好的设计框架。在Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。我们可以回想在之前做过的项目中,比如智慧背景,谷歌电子市场中,我们当把整个项目做完之后,对数据Model和视图View可能比较清晰,但是对于Controller就非常模糊了,因为在逻辑业务的处理与视图的操作经常会混合在一起,经常在一个Activity中一起混合处理这两者,所以我们对MVC设计模式中Controller非常的不清晰。简单的来说,MVC设计模式中,我们对控制逻辑业务的部分抽取的不彻底,这个时候我们就需要对Controller进行彻底的抽取,使得这三者之间的逻辑更独立,任务分工更加明确。
所以,我们将其中复杂的逻辑处理移至另外的一个类(Presneter)中时,Activity其实就是MVP模式中View,它负责UI元素的初始化,通过接口建立UI元素与Presenter的关联,复杂的逻辑交由Presenter处理,这就产生了MVP模式。
总结:MVC模式对逻辑业务的抽取不彻底,MVP是对数据、视图、逻辑三大模块更加彻底分工的设计模式
二、什么是MVP模式?
MVP代表Model,View和Presenter。
View层负责处理用户事件和视图部分的展示。在Android中,它可能是Activity或者Fragment类。负责UI的绘制和用户的交互
Model层负责访问数据。数据可以是远端的Server API,本地数据库或者SharedPreference等。 负责数据的检索,持久化等操作
Presenter层是连接(或适配)View和Model的桥梁。作为Model和View的中间协调部分,负责两者之间的业务逻辑处理
三、MVP模式的优缺点
优点:
1降低了数据与视图之间的耦合,
2层级职责更明显,
3易于单元测试
缺点:
1造成类数量增加,代码复杂度增加
2在某些场景下presenter的复用会产生接口冗余
3presenter中持有视图的引用,容易造成内存泄漏
四、MVP与MVC模式的区别
MVP模式与MVC模式从层级数据流向上来说一个主要的区别应该就是:MVC模式允许View层和Model层直接通讯.从图1和图2可以看到MVP和MVC的区别.
图1MVC模式中Model可以直接update data 到View层。所以当某个View的功能很复杂的时候,View和Model的耦合度可能会很高(并且在android的开发中Activity通常会充当controller&view的角色,结果Activity就很臃肿).而MVP模式就没有这个问题,View会抽象出来一系列操作UI的接口(Model层也可以),Presenter拿到的都是其他两个层级的接口来做业务逻辑的处理.这样不仅可以使View和Model之间的耦合度降低,还可以更易得进行单元测试.
图1 MVC设计模式
图2 MVP设计模式
通过以上的分析总结MVP和MVC的区别:
MVP模式:
·View不直接与Model交互,而是通过与Presenter交互来与Model间接交互
·Presenter与View的交互是通过接口来进行的,更有利于添加单元测试
·通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑
MVC模式:
·View可以与Model直接交互
·Controller是基于行为的,并且可以被多个View共享
·可以负责决定显示哪个View
五、MVP设计模式的案例分析
1Model层:
StudentBean类:封装学生相关的信息,也就是封装我们的数据
在学生类中我只定义了姓名和密码两个属性进行登陆界面的实现
package com.heima.mvp.model;
/**
* 创建: 馥溪凝
* 时间: 2016-11-24 下午 03:55.
* 描述: 封装学生相关的信息
*/
public class StudentBean {
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
LoginIntreface类: 学生类对外提供登陆的接口,是Model与Presenter之间沟通的桥梁
对于登陆界面来说,学生类只需要实现的一个登陆的业务逻辑,所以提供一个接口,里面只抽象出来一个登陆的方法,交给MVP模式中Presenter去处理复杂的业务逻辑
package com.heima.mvp.model;/** * 创建: 馥溪凝 * 时间: 2016-11-24 下午 03:58. * 描述: 学生类对外暴露登陆的接口 */public interface LoginInterface { void login(StudentBean studentBean);}
LoginImpl类: 获取登陆过程验证的数据,以及登陆结果的回调
package com.heima.mvp.model;/** * 创建: 馥溪凝 * 时间: 2016-11-24 下午 04:01. * 描述: 实例化LoginInterface接口,通过登陆监听将结果回调给Presenter */public class LoginImpl implements LoginInterface { public OnLoginListener mOnLoginListener; public LoginImpl(OnLoginListener mOnLoginListener) { this.mOnLoginListener = mOnLoginListener; } /** * 登陆过程的数据判断 * @param studentBean */ @Override public void login(StudentBean studentBean) { boolean status = false; String username = studentBean.getUsername(); String password = studentBean.getPassword(); if (username != null && "qwer".equals(username)){ if (password != null && "123".equals(password)){ status = true; } mOnLoginListener.loginStatus(status); } } /** * 登陆是否成功的状态接口 */ public interface OnLoginListener{ void loginStatus(boolean status); }}
2View层
LoginViewInterface类: 针对登陆界面抽取出处理逻辑业务相关的接口
对于登陆界面,我们需要对登陆界面进行什么操作,就在接口中定义操作的抽象方法。在本次案例中,需要获取用户名和密码,以及清空用户名和密码的简单操作和显示界面吐司的操作。
package com.heima.mvp.view;/** * 创建: 馥溪凝 * 时间: 2016-11-24 下午 04:07. * 描述: 针对View抽象出来一些列的接口 */public interface LoginViewInterface { public String getUsername(); public String getPassword(); public void clearUsername(); public void clearPassword(); public void showMsg(String msg);}
LoginActivity类: 登陆界面,相当于MVP设计模式中的View,主要是处理界面相关的操作。
从上面接口的定义中,可以看出来这个时候的Activity变得非常的薄弱了,里面一点逻辑也没有了,只有单纯的显示界面了。
package com.heima.mvp.view;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;import com.heima.mvp.R;import com.heima.mvp.presenter.LoginPresenter;/** * 描述: 登陆界面 * 描述: MVP设计模式中的View */public class LoginActivity extends AppCompatActivity implements LoginViewInterface{ // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } private EditText username; private EditText password; private LoginPresenter loginPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); init(); } /** * 初始化视图 */ private void init() { loginPresenter = new LoginPresenter(this); username = (EditText) findViewById(R.id.username); password = (EditText) findViewById(R.id.password); Button login = (Button) findViewById(R.id.login); Button clear = (Button) findViewById(R.id.clear); login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { loginPresenter.login(); } }); clear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { loginPresenter.clear(); } }); } /** 获取输入用户名 */ @Override public String getUsername() { return username.getText().toString().trim(); } /** 获取输入的密码 */ @Override public String getPassword() { return password.getText().toString().trim(); } /** 清除用户名 */ @Override public void clearUsername() { username.setText(""); } /** 清除密码 */ @Override public void clearPassword() { password.setText(""); } /** 显示登陆成功的信息 */ @Override public void showMsg(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); }}
3Presenter层
LoginPresenter类: 处理View层和Model层相关的逻辑业务,是MVP设计模式中的Presenter。
在这个逻辑的类中,处理登陆、清空、登陆成功之后干什么等的逻辑,通过接口与listener监听沟通着View与Model,连接着里面一些复杂的业务。
package com.heima.mvp.presenter;import com.heima.mvp.model.StudentBean;import com.heima.mvp.model.LoginImpl;import com.heima.mvp.view.LoginActivity;/** * 创建: 馥溪凝 * 时间: 2016-11-24 下午 04:30. * 描述: 掌握着View和Model的所有接口,处理接口中的相关逻辑 */public class LoginPresenter{ private LoginActivity loginActivity; private LoginImpl studnetImpl; public LoginPresenter(final LoginActivity loginActivity) { this.loginActivity = loginActivity; studnetImpl = new LoginImpl(new LoginImpl.OnLoginListener() { @Override public void loginStatus(boolean status) { //处理登陆结果的数据逻辑 String msg; if (status){ msg = "登陆成功"; }else { msg = "登录失败"; } loginActivity.showMsg(msg); } }); } /** * 处理登陆的业务逻辑 */ public void login() { StudentBean studentBean = new StudentBean(); studentBean.setUsername(loginActivity.getUsername()); studentBean.setPassword(loginActivity.getPassword()); studnetImpl.login(studentBean); } /** * 处理清楚的相关逻辑 */ public void clear() { loginActivity.clearPassword(); loginActivity.clearUsername(); }}
六、耦合子interactor
Interactor翻译过来就是耦合的意思,它在MVP设计模式中起到的其实就是一个粘合剂的角色。
我们发现每个presenter中都持有一个或多个的interactor,而每个interactor里面就是调用了一下api接口.那为什么不在presenter中直接调用api?那是因为我们从本地数据库,或者是服务器上获取的数据封装成Model,这个Model是不能直接在界面上使用的,我们需要将这个Model转化为ViewModel成为界面使用的数据。简单点说,就是我们从服务器或者数据库获取的数据封装成JavaBean之后,需要再一次进行转化成View中需要的JavaBean,而这个过程就叫interactor。
在presenter中,Presenter实现Interactor的回调接口,可以接收到ViewModel的实例,此时它在回调函数里面只需要将接收到的ViewModel绑定的View上面即可。可以看到,在这个过程中Presenter并没有触及到具体的实现,只是把View 和 ViewModel进行了绑定而已。当然你也可以把数据逻辑写在Presenter,但是Interactor就不存在了。
其实Interactor的存在,是为了Presenter更加的简化,当数据逻辑较为复杂的时候,interactor就会显示出它的价值了,因为interactor可以被复用,复用就会使得代码更加的简洁,使得数据的处理逻辑不会复杂。
- MVP模式分析
- MVP模式分析及简单例子
- MVC MVVM MVP Backbone 互动模式 架构模式总结分析
- Android中的MVP模式与MVC模式的比较分析
- MVP模式
- MVP模式
- MVP模式
- MVP模式
- MVP模式
- MVP模式
- MVP模式
- mvp模式
- MVP模式
- mvp模式
- MVP模式
- MVP模式
- mvp模式
- MVP模式
- 6、SQL Server:SqlServer时间日期处理函数及字符串转换
- 高斯模糊算法的全面优化过程分享。
- Laplacian surface editing
- Fence Repair(POJ-3253)
- PTA5-19 求链式线性表的倒数第K项
- MVP模式分析
- 自定义控件常用方法
- MySQL开启远程连接
- 虚幻UE4常见问题最全集合
- caffe源码深入学习2:blob.hpp+blob.cpp
- CCF之矩阵(java)
- 第二章photoshop基础操作
- cs231n 课程作业 Assignment 1
- ZOJ 3203 Light Bulb【数学推导&三分】