MVC,MVP的对比(附代码)一次搞懂!

首先看下我们的页面

一个edittext,一个获取用户信息的button,一个展示用户信息的textview

实现:点击按钮,根据用户输入的账号,获取账号信息并显示在textview上

现在我们用三种方式实现

(1)不使用任何模式

(2)mvc模式

(3)mvp模式

前提:我们定义bean类和callback类

 Account.class
package com.jyr.kotlindemo.designPatterns

//账号信息
 class Account {
    //账号名称
    var accountName: String = ""
    //账号等级
    var level: Int = 1
}
CallBack.class
package com.jyr.kotlindemo.designPatterns

interface CallBack {
    fun onSuccess(account: Account)
    fun onFail()
}
 

1. 不使用任何模式下,页面效果如下

ModelActivity.class
package com.jyr.kotlindemo.designPatterns

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.jyr.kotlindemo.R
import com.jyr.kotlindemo.designPatterns.mvc.MVCActivity
import com.jyr.kotlindemo.designPatterns.mvp.MVPActivity
import kotlin.random.Random

public class ModelActivity : AppCompatActivity(), View.OnClickListener {

    private lateinit var etCountId: EditText
    private lateinit var btnGetInfo: Button
    private lateinit var tvUserAccountInfo: TextView
    private lateinit var btnMvcMode: Button
    private lateinit var btnMvpModel: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_model)
        //初始化控件
        etCountId = findViewById<EditText>(R.id.et_account_id)
        btnGetInfo = findViewById<Button>(R.id.btn_get_info)
        tvUserAccountInfo = findViewById<TextView>(R.id.tv_user_account_info)
        btnMvcMode = findViewById<Button>(R.id.btn_mvc_mode)
        btnMvpModel = findViewById(R.id.btn_mvp_mode)
        btnGetInfo.setOnClickListener(this)
        btnMvcMode.setOnClickListener(this)
        btnMvpModel.setOnClickListener(this)
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.btn_get_info -> {
                getAccountData(getUserInputAccount(), object : CallBack {
                    override fun onSuccess(account: Account) {
                        showSuccessPage(account)
                    }

                    override fun onFail() {
                        showFailPage()
                    }
                })
            }
            R.id.btn_mvc_mode -> startActivity(Intent(this, MVCActivity::class.java))
            R.id.btn_mvp_mode -> startActivity(Intent(this, MVPActivity::class.java))
        }
    }

    //获取用户输入的信息
    fun getUserInputAccount(): String {
        return etCountId.text.toString()
    }

    //展示获取数据成功的界面
    fun showSuccessPage(account: Account) {
        tvUserAccountInfo.setText("用户名为${account.accountName},用户等级为${account.level}")
    }

    //展示获取数据失败的界面
    fun showFailPage() {
        tvUserAccountInfo.setText("获取用户信息失败")
    }

    //请求接口:获取账户的数据(次数模拟网络请求)
    fun getAccountData(accountName: String, callBack: CallBack) {
        //随机一个boolean
        val random = Random
        val nextBoolean = random.nextBoolean()
        if (nextBoolean) {
            //成功的话,返回用户信息
            val account = Account()
            account.accountName = accountName
            account.level = 100
            callBack.onSuccess(account)
        } else {
            callBack.onFail()
        }
    }
}
activity_model.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="@dimen/dp_20"
    tools:context=".designPatterns.ModelActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_18"
        android:text="不使用任何模式下" />

    <EditText
        android:id="@+id/et_account_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入账号"
        android:maxLines="1" />

    <Button
        android:id="@+id/btn_get_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_10"
        android:text="获取用户信息" />

    <TextView
        android:id="@+id/tv_user_account_info"
        android:text="用户信息:"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_20" />

    <Button
        android:id="@+id/btn_mvc_mode"
        android:layout_marginTop="@dimen/dp_40"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MVC模式" />

    <Button
        android:id="@+id/btn_mvp_mode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MVP模式" />

</LinearLayout>

2.使用mvc模式

MVCModel.class
package com.jyr.kotlindemo.designPatterns.mvc

import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
import kotlin.random.Random

class MVCModel {
    //请求接口:获取账户的数据(次数模拟网络请求)
    public fun getAccountData(accountName: String, callBack: CallBack) {
        //随机一个boolean
        val random = Random
        val nextBoolean = random.nextBoolean()
        if (nextBoolean) {
            //成功的话,返回用户信息
            val account = Account()
            account.accountName = accountName
            account.level = 100
            callBack.onSuccess(account)
        } else {
            callBack.onFail()
        }
    }
}
MVCActivity.class
package com.jyr.kotlindemo.designPatterns.mvc

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.jyr.kotlindemo.R
import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack

/**
 * MVC
 * model (请求网络数据) !!!!!!!!!!!!!新建model类
 * view (指的layout,view控件)
 * controller (指的activity,fragment)
 *
 * 1.需要新建一个接口,callback,里边定义onSuccess和onFail方法
 * 2.新建model类(来请求网络数据),里边getData方法,传进去一个callback,如果数据请求成功的话,就回调onSuccess,失败就回调onFail
 * 3.在activity中声明Model,并初始化,在需要网络请求的地方,通过model.getData,在onSuccess和onFail的回调里,设置UI
 * */
class MVCActivity : AppCompatActivity(), View.OnClickListener {

    private lateinit var etCountId: EditText
    private lateinit var btnGetInfo: Button
    private lateinit var tvUserAccountInfo: TextView
    private lateinit var mvcModel: MVCModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_m_v_c)
        //初始化控件
        etCountId = findViewById<EditText>(R.id.et_account_id)
        btnGetInfo = findViewById<Button>(R.id.btn_get_info)
        tvUserAccountInfo = findViewById<TextView>(R.id.tv_user_account_info)
        btnGetInfo.setOnClickListener(this)
        mvcModel = MVCModel()
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.btn_get_info -> {
                mvcModel.getAccountData(getUserInputAccount(), object : CallBack {
                    override fun onSuccess(account: Account) {
                        showSuccessPage(account)
                    }

                    override fun onFail() {
                        showFailPage()
                    }
                })
            }
        }
    }

    //获取用户输入的信息
    fun getUserInputAccount(): String {
        return etCountId.text.toString()
    }

    //展示获取数据成功的界面
    fun showSuccessPage(account: Account) {
        tvUserAccountInfo.setText("用户名为${account.accountName},用户等级为${account.level}")
    }

    //展示获取数据失败的界面
    fun showFailPage() {
        tvUserAccountInfo.setText("获取用户信息失败")
    }
}
activity_m_v_c.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="@dimen/dp_20"
    tools:context=".designPatterns.ModelActivity">

    <TextView
        android:id="@+id/tv_mode_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MVC模式下"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_18" />

    <EditText
        android:id="@+id/et_account_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入账号"
        android:maxLines="1" />

    <Button
        android:id="@+id/btn_get_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_20"
        android:text="获取用户信息" />

    <TextView
        android:id="@+id/tv_user_account_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_20"
        android:text="用户信息:" />

</LinearLayout>

3.mvp模式

MVPModel.class
package com.jyr.kotlindemo.designPatterns.mvp

import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
import kotlin.random.Random

class MVPModel {
    //请求接口:获取账户的数据(次数模拟网络请求)
    public fun getAccountData(accountName: String, callBack: CallBack) {
        //随机一个boolean
        val random = Random
        val nextBoolean = random.nextBoolean()
        if (nextBoolean) {
            //成功的话,返回用户信息
            val account = Account()
            account.accountName = accountName
            account.level = 100
            callBack.onSuccess(account)
        } else {
            callBack.onFail()
        }
    }
}
IMVPView接口
package com.jyr.kotlindemo.designPatterns.mvp

import com.jyr.kotlindemo.designPatterns.Account

interface IMVPView {

    //获取用户输入的信息
    fun getUserInputAccount(): String

    //展示获取数据成功的界面
    fun showSuccessPage(account: Account)

    //展示获取数据失败的界面
    fun showFailPage()
}
MVPPresenter.class
package com.jyr.kotlindemo.designPatterns.mvp

import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack

class MVPPresenter {

    private var mvpModel: MVPModel
    private var imvpView: IMVPView

    constructor(imvpView: IMVPView) {
        this.imvpView = imvpView
        mvpModel = MVPModel()
    }

    fun getData(account: String) {
        mvpModel.getAccountData(account, object : CallBack {
            override fun onSuccess(account: Account) {
                imvpView.showSuccessPage(account)
            }

            override fun onFail() {
                imvpView.showFailPage()
            }

        })
    }
}
MVPActivity.class
package com.jyr.kotlindemo.designPatterns.mvp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import com.jyr.kotlindemo.R
import com.jyr.kotlindemo.designPatterns.Account
import com.jyr.kotlindemo.designPatterns.CallBack
import com.jyr.kotlindemo.designPatterns.mvc.MVCModel

/**
 * MVP
 * model (请求网络数据) !!!!!!!!!!!!!新建model类
 * view (指的layout,view控件)!!!!!!!!!!新建view类
 * presenter (指的activity,fragment)!!!!!!m层和p层的桥梁
 *
 * m层和v层不直接交互,通过presenter来作为沟通的桥梁
 * 用户点击页面,p通知m去请求数据,m请求数据完成后把结果回调给p,p再告诉v,v再去显示页面
 * 全程m和v层没有直接交流
 *
 * 1.需要新建一个接口,callback,里边定义onSuccess和onFail方法
 * 2.新建model类(来请求网络数据),里边getData方法,传进去一个callback,如果数据请求成功的话,就回调onSuccess,失败就回调onFail
 * 3.新建IView接口,里边定义页面显示的一些方法(showSuccessPage,showFailPage)
 * 4.新建一个presenter类,声明model和view,在构造方法里,传进来参数view,实例化model
 *   创建一个getData的方法,里边调用model的getData方法,然后在成功和失败的回调里,用view层设置页面
 * 5.在activity里声明Presenter,并初始化,在需要网络请求的地方,通过Presenter.getData
 *  在activity中实现view接口,重写它的方法,在这些重写的方法里设置UI
 *
 *
 *  MVC和MVP的区别(mvc和mvp的优缺点)
 *  mvc的话,m和v还是可以直接交互的,代码还是耦合比较高,一些逻辑简单的页面可以使用mvc
 *  mvp的话,例如点击页面,v通知p,p通知m去获取数据,m获取数据之后把结果传给p,p再传给v
 *           m层和v层不能直接交互,他们之间需要通过presenter来作为桥梁沟通
 *          降低了代码的耦合性,但是也会增加一些类
 *
 *
 *   MVVM的话,就是在MVP的基础上,增加了数据的双向绑定,数据绑定是通过databinding来实现的
 * */
class MVPActivity : AppCompatActivity(), View.OnClickListener, IMVPView {
    private lateinit var tvModeName: TextView
    private lateinit var etCountId: EditText
    private lateinit var btnGetInfo: Button
    private lateinit var tvUserAccountInfo: TextView
    private lateinit var mvpPresenter: MVPPresenter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_m_v_c)
        //初始化控件
        tvModeName = findViewById(R.id.tv_mode_name)
        etCountId = findViewById<EditText>(R.id.et_account_id)
        btnGetInfo = findViewById<Button>(R.id.btn_get_info)
        tvUserAccountInfo = findViewById<TextView>(R.id.tv_user_account_info)
        btnGetInfo.setOnClickListener(this)
        tvModeName.setText("MVP模式")
        mvpPresenter = MVPPresenter(this)
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.btn_get_info -> {
                mvpPresenter.getData(getUserInputAccount())
            }
        }
    }

    override fun getUserInputAccount(): String {
        return etCountId.text.toString()
    }

    override fun showSuccessPage(account: Account) {
        tvUserAccountInfo.setText("用户名为${account.accountName},用户等级为${account.level}")
    }

    override fun showFailPage() {
        tvUserAccountInfo.setText("获取用户信息失败")
    }
}
activity_m_v_c.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="@dimen/dp_20"
    tools:context=".designPatterns.ModelActivity">

    <TextView
        android:id="@+id/tv_mode_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MVC模式下"
        android:textColor="@color/black"
        android:textSize="@dimen/sp_18" />

    <EditText
        android:id="@+id/et_account_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入账号"
        android:maxLines="1" />

    <Button
        android:id="@+id/btn_get_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_20"
        android:text="获取用户信息" />

    <TextView
        android:id="@+id/tv_user_account_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_20"
        android:text="用户信息:" />

</LinearLayout>

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值