最近想要重构代码,因为项目需要给几个学校使用,而每个学校的界面是有差别的,但是功能几乎一模一样,虽然用gradle的分支可以做到代码的差异,但是公共部分的代码逻辑也越来越多,所以想重构一下,最近比较火的MVP模式看了一下,觉得很合适,不过网上很多资料也是抄来抄去,有的还有错误,就想按照自己的理解把MVP模式描述一下,方便他人理解,先说一下大家最熟悉的MVC设计模式吧
它们之间的关系如下图所示:
View传送指令到Controller,Controller完成业务逻辑后,改变Model的状态,Model将新的数据发送到View,这就是MVC模式的处理逻辑。
可以看到,M层和C层耦合了
然后看一下MVP,我下面的文字以I开头的是接口的意思(手打的图好累...)
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设计模式是个人理解,如果有误请指正,谢谢,共同探讨,共同进步