Android 設計模式之 淺談MVP,androidmvp
一.概述
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來對登陸資料判斷
public class UserBean { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
UserBiz通過抽象出一個介面
public interface UserBiz { public void login(UserBean login);}
UserBizImpl執行個體化介面,並且通過登陸監聽將結果回調給Presenter
public class UsrBizImpl implements UserBiz{ private OnLoginListener listener; public UsrBizImpl(OnLoginListener listener){ this.listener = listener; } @Override public void login(UserBean login) { boolean status = false; String username,password; username = login.getUsername(); password = login.getPassword(); if (username != null && "asdf".equals(username)) if (password != null && "123".equals(password)) status = true; listener.loginStatus(status); }}
3.View層
把View層針對控制項操作抽象出來一些列的介面
public interface LoginView { public String getUsername(); public String getPassword(); public void clearUsername(); public void clearPassword(); public void showMsg(String msg);}
在Activity裡面實現該介面的控制項操作,並且初始化Presenter,這是可以看到Activity裡面沒有邏輯處理,只是對UI的控制項進行資料或者行為的操作,所有的動作都是有Presenter的介面來實現,這樣在項目裡面會極大得精簡Activity的體積.
public class LoginActivity extends Activity implements LoginView{ private EditText username, password; private Button login, clear; private LoginPresenter loginPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); init(); } private void init(){ loginPresenter = new LoginPresenterImpl(this); username = (EditText) findViewById(R.id.username); password = (EditText) findViewById(R.id.pass); login = (Button) findViewById(R.id.login); clear = (Button) findViewById(R.id.clear); login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loginPresenter.login(); } }); clear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loginPresenter.clear(); } }); } @Override public String getUsername() { return username.getText().toString(); } @Override public String getPassword() { return password.getText().toString(); } @Override public void clearUsername() { username.setText(""); } @Override public void clearPassword() { password.setText(""); } @Override public void showMsg(String msg) { Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); }}
4.Presenter層
在Presenter層裡面,Presenter掌握著View和Model的所有介面,Presenter就可以根據不同的商務邏輯通過MV兩層的介面來實現特定的功能,讓M和V獨立出來.
public class LoginPresenterImpl implements LoginPresenter, OnLoginListener{ private UserBiz userBiz; private LoginView loginView; public LoginPresenterImpl(LoginView loginView){ this.loginView = loginView; userBiz = new UsrBizImpl(this); } @Override public void login() { UserBean login = new UserBean(); login.setUsername(loginView.getUsername()); login.setPassword(loginView.getPassword()); userBiz.login(login); } @Override public void clear() { loginView.clearPassword(); loginView.clearUsername(); } @Override public void loginStatus(boolean status) { String msg; if (status) msg = "login succeed"; else msg = "login failed"; loginView.showMsg(msg); }}
5.Demo
CSDN下載
三.總結
簡單得用了下MVP,也有跟朋友討論了一下,好多人都說這個看著挺不錯的,但是用著很麻煩。確實現在Android項目用MVP的不是佔多數,帶著一些疑惑樓主就想去瞭解一下android原生程式裡面是用的什麼風格的,之前也有看過一些android源碼,但是都是斷斷續續的,也好久沒有寫過部落格了,本著對技術的熱愛,計劃重新開啟擼android源碼的計劃(從Android原生的系統程式到framework再一路向下),現在希望自己能夠堅持下來,並且產出一個部落格的系列和大家一起分享和成長.