Android中MVC与MVP框架的对比及MVP实例(登录实例)及开闭原则简析

首先先明确一下MVC和MVP到底是设计模式还是框架?
设计模式是从coding层面提炼出来的一种总结,用来使得代码的耦合度达到最大限度的分离,从而可以使你的代码更好的被复用,更容易被替换,更好的拥抱需求的变化。
架构则是着眼于更全局的高度,是保证软件的可用性,可扩展性,可伸缩性,安全等等一系列的指标。
设计模式服务于架构,是实现架构设计的具体手段,架构是从整体上着手设计具有宏观性。
所以说MVC和MVP是一种框架架构模式,不是设计模式。

一 MVC:
是一种经典的三层架构模式,目的是将数据层和视图层分离,使它们的耦合度降低,符合面向对象设计的单一原则。
在这里插入图片描述

  • M:Model(数据层),实体模型,包含网络请求、数据库读取、文件读取、逻辑运算、业务bean类等等,实际中常用来对数
    据的封装和保存。
  • V:View(视图层),视图界面,对应于布局文件,更具体的就是视图控件,例如:TextView、ImageView等等。
  • C:Controller(控制层),将model数据展示在view上,控制应用程序的流程,业务逻辑的处理;对应于工程宏的
    Activity、Fragment、Adapter等。
  • 优点:站在Android的角度看个人认为,MVC适用于中小型项目的开发,其开发周期短,效率高,模块职责划分明确。
    主要划分层M,V,C三个模块,利于代码的维护。
  • 缺点:虽然MVC将数据、视图、控制器划分三层看似层与层之间是耦合度降低了,但是实际开发中并没有起到完全的解耦。因为View对应的XML文件实际能做的事情很少,很多界面显示由Controllor对应的Activity或者Fragment给做了,导致View和Controller之间的分层很模糊,也就是Activity充当Controllor也充当了View,也就造成Activity的职责不清,导致Controllor层非常的臃肿,也进一步导致了耦合度非常的高。

二 MVP:
基于MVC衍生出来的一种模式,将MVC中的C优化成了P,P负责业务核心逻辑,并阻断了View和Model的直接联系,从而使View和Model更加专注自身的逻辑。适合中大型项目。

MVP实际上是使View变薄,View和Model完全解耦。
在这里插入图片描述

  • M:和MVC中的M是一样。

  • V:Activity、Fragment,View会包含一个或者多个P的引用用P的逻辑,P也可以控制V的显示。

  • P(Presenter):作为V和M的桥梁,负责从M中拿数据处理后返所以每个P通常包含一个或者多个接口协议。

  • 优点:
    1.View和 Model之间的耦合度降低,结构清晰,维护方便。
    2.便于单元测试。
    3.代码复用率高,扩展性强。
    4.代码框架更适用于快速迭代开发。

  • 缺点:
    1.类相对较多,如果一个Presenter被多个View引用,那么每个View中都要创建Presenter对象。耦合度提高,为了解决这个问题,后续引入Dagger。

三 MVP的实例(登录实例)

下面会根据这张图进行分析
在这里插入图片描述

步骤:
1.创建登录View的接口ILoginView
2.创建登录Model的接口ILoginModel
3.创建LoginActivity作为View的实例,实现ILoginView接口
4.创建LoginModel作为Model的实例,实现ILoginModel接口
5.创建LoginPresennter文件
6.效果图

具体实现步骤:
1.创建登录View的接口ILoginView

package showly.com.mytest.view;

public interface ILoginView {
    /*
    * 登录时view需要知道是否登录成功后,更新ui
    * */
    public void isLoginSuccess(boolean success);
}

2.创建登录Model的接口ILoginModel

package showly.com.mytest.model;

public interface ILoginModel {
    /*
    * 需要判断用户输入的账号与密码是否正确
    * */
    public boolean login(String userName, String password);
}

3.创建LoginActivity作为View的实例,实现ILoginView接口

package showly.com.mytest.view;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import showly.com.mytest.R;
import showly.com.mytest.presenter.LoginPresenter;

public class LoginActivity extends AppCompatActivity implements ILoginView {

    private EditText mEtUserName;
    private EditText mMEtPsw;
    private Button mLoginBtn;
    private TextView mTvLoginSuccess;
    private LoginPresenter mLoginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initListener();
    }

    private void initListener() {
        mLoginPresenter = new LoginPresenter();
        mLoginPresenter.setLoginView(this);//将View传递给Presenter层

        mLoginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //根据用户输入的账号 密码进行登录判断
                String userName = mEtUserName.getText().toString();
                String psw = mMEtPsw.getText().toString();
                mLoginPresenter.login(userName, psw);
            }
        });
    }

    private void initView() {
        mEtUserName = (EditText) findViewById(R.id.et_userName);
        mMEtPsw = (EditText) findViewById(R.id.et_psw);
        mLoginBtn = (Button) findViewById(R.id.btn_login);
        mTvLoginSuccess = (TextView) findViewById(R.id.tv_success);
    }

    @Override
    public void isLoginSuccess(boolean success) {
        //更新UI
        if (success) {
            mTvLoginSuccess.setText("登录成功");
            mTvLoginSuccess.setTextColor(Color.BLUE);
        } else {
            mTvLoginSuccess.setText("登录失败");
            mTvLoginSuccess.setTextColor(Color.RED);
        }
    }
}

4.创建LoginModel作为Model的实例,实现ILoginModel接口

package showly.com.mytest.model;

/**
 * Created by Administrator on 2018/12/12.
 */

public class LoginModel implements ILoginModel {
    @Override
    public boolean login(String userName, String password) {
        /*
        * 在这里可以请求服务器或者数据库中的数据
        * 请求数据省略,假设请求回来的数据为name:showly password:123456
        * */
        if(userName.equals("showly")){
            if(password.equals("123456")){
                return true;
            }
        }
        return false;
    }
}

5.创建LoginPresennter文件

package showly.com.mytest.presenter;

import showly.com.mytest.model.ILoginModel;
import showly.com.mytest.model.LoginModel;
import showly.com.mytest.view.ILoginView;

/**
 * Created by Administrator on 2018/12/12.
 */

public class LoginPresenter {
    /*
    * presenter需要持有view与model接口的引用
    * */
    private ILoginView mILoginView;
    private ILoginModel mILoginModel;

    //View层中持有presenter的引用,所以可以创建方法从View中传递过来
    public void setLoginView(ILoginView loginView) {
        this.mILoginView = loginView;
    }

    //Model层中不持有presenter的引用,所以LoginPresenter构建方法中新建对象
    public LoginPresenter() {
        //创建Model对象
        mILoginModel = new LoginModel();
    }

    //presenter持有View与Model,创建方法作为两者的中间站
    public void login(String name, String psw) {
        //将用户输入的用户名 密码传递到Model层进行判断
        boolean isSuccess = mILoginModel.login(name, psw);
        //将Model层对比数据后的结果返回
        mILoginView.isLoginSuccess(isSuccess);
    }

}

6.效果图
在这里插入图片描述

四 开闭原则介绍
在这里介绍一下开闭原则,我们在MVP的实例中看到,我们的View和Model是用接口的形式与Presenter进行关联,有没想过这是为什么呢?

这就涉及到开闭原则了,也就是对扩展进行开放,对修改进行关闭。
举个例子:
我们定义一个接口:

public interface ILoginModel {
    public LoginBean getLoginBean();
}

然后创建LoginModel实现这个接口:

public class LoginModel implements ILoginModel {
    @Override
    public LoginBean getLoginBean() {
      //假设这里用原生系统SQLiteOpenHelper
      //查询数据库的代码
    }
}

此时项目经理说用原生的数据库查询不好,需要换GreenDao进行查询,这个时候我们就需要对getLoginBean方法进行修改,而项目中其它很多地方已经使用了该方法,那我们要怎样才能降低修改的成本呢?

其实我们刚开始设计的时候,就应该考虑到这个问题,根据开闭原则,我们可以让其它地方使用以下的方法进行调用:

  public void getData(ILoginModel  loginModel) {
  	loginModel.getLoginBean();
  }

这样需要修改的时候,我们可以对修改进行关闭,也就是不修改LoginModel,而是新创建GreenDaoModel,这样就能降低修改的成本。
以上属于个人理解,不对的地方请指教。

五 登录Demo代码:公众号回复"MVPDemo"即可获取


小编整理了一份Android电子书籍,需要的童鞋关注底部公众号(longxuanzhigu)回复:“e_books” 即可获取哦!
在这里插入图片描述

以下是个人公众号(longxuanzhigu),之后发布的文章会同步到该公众号,方便交流学习Android知识及分享个人爱好文章:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值