最近想要重構代碼,因為項目需要給幾個學校使用,而每個學校的界面是有差別的,但是功能幾乎一模一樣,雖然用gradle的分支可以做到代碼的差異,但是公共部分的代碼邏輯也越來越多,所以想重構一下,最近比較火的MVP模式看了一下,覺得很合適,不過網上很多資料也是抄來抄去,有的還有錯誤,就想按照自己的理解把MVP模式描述一下,方便他人理解,先說一下大家最熟悉的MVC設計模式吧
它們之間的關系如下圖所示:
View傳送指令到Controller,Controller完成業務邏輯后,改變Model的狀態,Model將新的數據發送到View,這就是MVC模式的處理邏輯。
image.png
可以看到,M層和C層耦合了
然后看一下MVP,我下面的文字以I開頭的是接口的意思(手打的圖好累...)
深度截圖20161205160152.png
MVP和MVC最大的區別是P層解耦了M層和C層,邏輯層和視圖層完全分離了,下面用代碼來說話,先來MVC模式的,點擊按鈕,V層發送點擊事件到了C層(Activity同時是C層也是V層),然后C層調用M層獲取到了數據,然后根據數據更新C層,和上圖的MVC對應
public interface ICallback{
void receive(boolean success);
}
public class LoginModel{
public void login(String name,String password,ICallback callback){
WebApi.login(name,password,callback);
}
}
public class LoginActivity extends Activity{
private LoginModel mLoginModel;
private EditText mUserNameEt;
private EditText mPasswordEt;
private Button mSubmitBtn;
public void onCreate(......){
mLoginModel = new LoginModel(...);
mSubmitBtn.setOnClickListener(new OnClickListener(View view){
mLoginModel.login(mUserNameEt.get...,mPasswordEt.get...,new ICallback(){
public void receive(boolean success){
if(success){
startActivity(new Intent(this,MainActivity.class));
finish();
} else {
Toast.makeText(this,"登錄失敗",Toast.LENGTH_SHORT).show();
}
}
});
});
}
}
我們再來看一下用MVP模式怎么寫,文章下面的評論有哥們說寫個契約類,我查了一下,寫個契約類是比較方便,所以下面的代碼是我改過的
public interface ILoginContract {
public interface ILoginModel{
public void login(String name,String password,ICallback callback);
}
public interface ILoginPresenter{
public void login(String name,String password);
}
public interface ILoginView{
public void showDialog();
public void dismissDialog();
public void showToast(String message);
public void navigateToMain();
}
}
public class PresenterImpl implements ILoginPresenter,ICallback{
private ILoginView mLoginView;
private ILoginModel mLoginModel;
public PresenterImpl(ILoginView loginView){
this.mLoginView = loginView;
this.mLoginModel = new LoginModelImpl();
}
public void login(String name,String password){
if(isEmpty(name)||isEmpty(password)){
this.mLoginView.showToast("用戶名或密碼不能為空");
return;
}
this.mLoginModel.login(name,password,this);
}
public void receive(boolean success){
if(success){
this.mLoginView.navigateToMain();
}else{
this.mLoginView.showToast("登錄失敗");
}
}
private boolean isEmpty(String text){
return text==null||"".equals(text)?true:false;
}
}
public class LoginActivity extends Activity implements ILoginView{
private IPresenter mPresenter;
private EditText mUserNameEt;
private EditText mPasswordEt;
private Button mSubmitBtn;
public void onCreate(......){
mPresenter = new PresenterImpl(this);
mSubmitBtn.setOnClickListener(new OnClickListener(View view){
mPresenter.login(mUserNameEt.getText().toString(),
mPasswordEt.getText().toString());
});
}
public void showDialog(){
//顯示一個轉圈的dialog;
}
public void dismissDialog(){
//隱藏轉圈的dialog;
}
public void showToast(String message){
Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}
public void navigateToMain(){
startActivity(new Intent(this,MainActivity.class));
finish();
}
}
MVP的類和代碼確實要多一些,但是這些是非常值得的,可以看出現在的代碼邏輯要比MVC模式寫起來更清晰,代碼測試也更簡單,甚至可以在沒有頁面效果圖只有功能的時候完成功能,UI的改變也不會影響任何的業務代碼。
以上MVP設計模式是個人理解,如果有誤請指正,謝謝,共同探討,共同進步