欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android设计模式之浅谈MVP

程序员文章站 2024-03-16 12:59:10
...

一.概述

 

MVP(Model-View-Presenter) 是总所周知MVC模式的一个演变,他们的主要目的都是划分模块职责,降低模块耦合,易测试,提高代码复用,这里主要针对Android平台来简单分析MVP.

 

1.层级责任

Model:       负责数据的检索,持久化等操作

View:         负责UI的绘制和用户的交互

Presenter: 作为Model和View的中间协调部分,负责两者之间的业务逻辑处理

 

2.与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之间的耦合度降低,还可以更易得进行单元测试.

 

Android设计模式之浅谈MVP  

图1:MVC模式

 

   Android设计模式之浅谈MVP  

图2:MVP模式

 

 

3.MVP的优缺点

优点:降低耦合,层级职责更明显,易于单元测试

缺点:造成类数量爆炸,代码复杂度和学习成本高,在某些场景下presenter的复用会产生接口冗余

 

 

二. MVP简单的实例

使用MVP 写一个简单的登陆功能,主页就两个按钮:Login 和 Clear

1.项目结构

 

  Android设计模式之浅谈MVP

 

2.Model层

包含有一个实体UserBean用来承载数据和UserBiz来对登陆数据判断

 

 
  1. public class UserBean {

  2. private String username;

  3. private String password;

  4.  
  5. public String getUsername() {

  6. return username;

  7. }

  8.  
  9. public void setUsername(String username) {

  10. this.username = username;

  11. }

  12.  
  13. public String getPassword() {

  14. return password;

  15. }

  16.  
  17. public void setPassword(String password) {

  18. this.password = password;

  19. }

  20. }

 

UserBiz通过抽象出一个接口

 

 

 
  1. public interface UserBiz {

  2. public void login(UserBean login);

  3. }


UserBizImpl实例化接口,并且通过登陆监听将结果回调给Presenter

 

 

 
  1. public class UsrBizImpl implements UserBiz{

  2. private OnLoginListener listener;

  3.  
  4. public UsrBizImpl(OnLoginListener listener){

  5. this.listener = listener;

  6. }

  7.  
  8. @Override

  9. public void login(UserBean login) {

  10. boolean status = false;

  11. String username,password;

  12. username = login.getUsername();

  13. password = login.getPassword();

  14. if (username != null && "asdf".equals(username))

  15. if (password != null && "123".equals(password))

  16. status = true;

  17. listener.loginStatus(status);

  18. }

  19. }


3.View层

 

把View层针对控件操作抽象出来一些列的接口

 

 
  1. public interface LoginView {

  2. public String getUsername();

  3. public String getPassword();

  4. public void clearUsername();

  5. public void clearPassword();

  6. public void showMsg(String msg);

  7. }


在Activity里面实现该接口的控件操作,并且初始化Presenter,这是可以看到Activity里面没有逻辑处理,只是对UI的控件进行数据或者行为的操作,所有的动作都是有Presenter的接口来实现,这样在项目里面会极大得精简Activity的体积.

 

 

 
  1. public class LoginActivity extends Activity implements LoginView{

  2. private EditText username, password;

  3. private Button login, clear;

  4. private LoginPresenter loginPresenter;

  5.  
  6. @Override

  7. protected void onCreate(Bundle savedInstanceState) {

  8. super.onCreate(savedInstanceState);

  9. setContentView(R.layout.activity_login);

  10. init();

  11. }

  12.  
  13. private void init(){

  14. loginPresenter = new LoginPresenterImpl(this);

  15. username = (EditText) findViewById(R.id.username);

  16. password = (EditText) findViewById(R.id.pass);

  17. login = (Button) findViewById(R.id.login);

  18. clear = (Button) findViewById(R.id.clear);

  19. login.setOnClickListener(new View.OnClickListener() {

  20. @Override

  21. public void onClick(View view) {

  22. loginPresenter.login();

  23. }

  24. });

  25.  
  26. clear.setOnClickListener(new View.OnClickListener() {

  27. @Override

  28. public void onClick(View view) {

  29. loginPresenter.clear();

  30. }

  31. });

  32. }

  33.  
  34. @Override

  35. public String getUsername() {

  36. return username.getText().toString();

  37. }

  38.  
  39. @Override

  40. public String getPassword() {

  41. return password.getText().toString();

  42. }

  43.  
  44. @Override

  45. public void clearUsername() {

  46. username.setText("");

  47. }

  48.  
  49. @Override

  50. public void clearPassword() {

  51. password.setText("");

  52. }

  53.  
  54. @Override

  55. public void showMsg(String msg) {

  56. Toast.makeText(this, msg, Toast.LENGTH_LONG).show();

  57. }

  58. }


4.Presenter层

 

在Presenter层里面,Presenter掌握着View和Model的所有接口,Presenter就可以根据不同的业务逻辑通过MV两层的接口来实现特定的功能,让M和V独立出来.

 

 
  1. public class LoginPresenterImpl implements LoginPresenter, OnLoginListener{

  2. private UserBiz userBiz;

  3. private LoginView loginView;

  4.  
  5. public LoginPresenterImpl(LoginView loginView){

  6. this.loginView = loginView;

  7. userBiz = new UsrBizImpl(this);

  8. }

  9.  
  10. @Override

  11. public void login() {

  12. UserBean login = new UserBean();

  13. login.setUsername(loginView.getUsername());

  14. login.setPassword(loginView.getPassword());

  15. userBiz.login(login);

  16. }

  17.  
  18. @Override

  19. public void clear() {

  20. loginView.clearPassword();

  21. loginView.clearUsername();

  22. }

  23.  
  24. @Override

  25. public void loginStatus(boolean status) {

  26. String msg;

  27. if (status)

  28. msg = "login succeed";

  29. else

  30. msg = "login failed";

  31. loginView.showMsg(msg);

  32. }

  33. }