前言
以前有学过,感觉理解不了,然后又用不到,就不了了之了 ,现在因为实习公司的项目有用到,如果不学的话感觉根本看不懂项目(其实学完之后还是看不懂),所以就重新学过,顺便记录一下。
从全局的观念来看,mvp模式只是一个思想,并没有具体的,标准的编码规定,下面所说的预备知识,是为优化MVP模式所服务的。
预备知识
- 面向接口的编程思想
- 向上转型的概念
- 解耦
面向接口编程
接口的概念:
在Java程序设计语言中,接口不是类,而是对希望符合这个接口的类的一组需求(出自《Java核心卷一》p222页)
面向接口编程呢,就是在开始开发前,先定义好接口(可以理解为先列出一组需求),然后再进行开发
向上转型
即父类引用指向子类对象(即多态),看完下面的代码应该更好理解些
public interface IStudent {
String getName();
}
public class Student implements IStudent{//此时IStudent是父类,Student是子类
@Override
public String getName() {
return "任我行";
}
}
public class Test {
public static void main(String[] args) {
IStudent iStudent;
iStudent=new Student();//父类引用指向子类的对象,这里做了向上转型
System.out.println("学生的名字是:"+iStudent.getName());//打印结果:学生的名字是:任我行
}
}
解耦
解耦即降低依赖性
MVP模式
我觉得MVP模式的灵魂就是presenter层同时持有view层和model层的引用(请联系上边的向上转型的概念)。
照此逻辑,我们简单实现一个常见的登录模块。根据面向接口编程,我们首先列出我们的接口(需求):
/**
* View层的需求
*/
public interface IView {
//1. 获取用户的输入信息
public User getViewUser();
//2. 登录成功的操作
public void loginSuceess();
//3. 登录失败后的操作
public void loginFail();
}
/**
* Model层的需求
*/
public interface IModel {
//判断信息是否正确
public boolean isOk(User user);
}
/**
* presenter层的需求
*/
public interface IPresenter {
//登录操作
public void login();
}
好了,接口写完,现在去实现接口:
public class View extends AppCompatActivity implements IView{
private EditText mUsername;
private EditText mPassword;
private Button mButton;
private IPresenter iPresenter;//present的引用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUsername = findViewById(R.id.et_username);
mPassword = findViewById(R.id.et_password);
mButton = findViewById(R.id.btn_login);
iPresenter = new Presenter(this);//父类引用指向子类对象,向上转型,这个this指向的是View本身,也就是是传入了一个IView的子类对象
//此时Presenter同时持有Model层和View层的对象
mButton.setOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(android.view.View v) {
iPresenter.login();//此操作会执行Pressenter对象的login方法
}
});
}
//实现IView的需求
@Override
public User getViewUser() {
return new User(mUsername.getText().toString(),mPassword.getText().toString());
}
@Override
public void loginSuceess() {
Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void loginFail() {
Toast.makeText(this, "登录失败!", Toast.LENGTH_SHORT).show();
}
}
public class Model implements IModel{
//IModel的需求
@Override
public boolean isOk(User user) {
if (user.getUsername().equals("root")&&user.getPassword().equals("123")){
return true;
}
return false;
}
}
我觉得mvp模式的核心在此
//presenter层,联系model和view的枢纽
public class Presenter implements IPresenter {
private IModel iModel;
private IView iView;
public Presenter(IView iView) {
this.iModel = new Model();//向上转型
this.iView = iView;//向上转型
}
//IPresenter的需求
@Override
public void login() {//当View层点击button的时候,将会调用到这个方法
if (iModel.isOk(iView.getViewUser())){
iView.loginSuceess();//执行view层的loginSuceess
}else {
iView.loginFail();//执行view层的loginFail
}
}
}
model,view,presenter的接口,就像是三条引子,把它们联系在了一起
实际的开发中
感觉mvp模式比普通的开发模式好不到哪里去,而且每次使用还都要定义一大堆接口,麻烦死咯,不过好处是逻辑更加清晰了些(好像就只有这个好处。。)
参考资料
- 一步步带你精通MVP
- Android MVP架构从入门到精通-真枪实弹
- 浅谈 MVP in Android
- java提高篇(三)-----理解java的三大特性之多态
- 面向接口编程思想(的好处)
- Java的向上转型与向下转型