Android設計模式之淺談MVP

一.概述

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之間的耦合度降低,還可以更易得進行單元測試.


  

圖1:MVC模式


     

圖2:MVP模式


3.MVP的優缺點

優點:降低耦合,層級職責更明顯,易於單元測試

缺點:造成類數量爆炸,代碼複雜度和學習成本高,在某些場景下presenter的複用會產生接口冗餘



二. MVP簡單的實例

使用MVP 寫一個簡單的登陸功能,主頁就兩個按鈕:Login 和 Clear

1.項目結構


  


2.Model層

包含有一個實體UserBean用來承載數據和UserBiz來對登陸數據判斷

[java] view plain copy
  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通過抽象出一個接口


[java] view plain copy
  1. public interface UserBiz {  
  2.     public void login(UserBean login);  
  3. }  

UserBizImpl實例化接口,並且通過登陸監聽將結果回調給Presenter

[java] view plain copy
  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層針對控件操作抽象出來一些列的接口

[java] view plain copy
  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的體積.

[java] view plain copy
  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獨立出來.

[java] view plain copy
  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. }  

5.Demo下載地址 

CSDN下載


三.總結

簡單得用了下MVP,也有跟朋友討論了一下,好多人都說這個看着挺不錯的,但是用着很麻煩。確實現在Android項目用MVP的不是佔多數,帶着一些疑惑樓主就想去了解一下android原生程序裏面是用的什麼風格的,之前也有看過一些android源碼,但是都是斷斷續續的,也好久沒有寫過博客了,本着對技術的熱愛,計劃重新開啓擼android源碼的計劃(從Android原生的系統程序到framework再一路向下),現在希望自己能夠堅持下來,並且產出一個博客的系列和大家一起分享和成長.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章