IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> MV*架构模式模式使用学习 -> 正文阅读

[开发测试]MV*架构模式模式使用学习

在开发应用程序的时候,以求更好的管理应用程序的复杂性,基于职责分离(Speration of Duties)的思想都会对应用程序进行分层.

软件工程熟悉的概念:高内聚,低耦合

耦合:

粗略地说,耦合就是两个东西通过某种作用连接在了一起。(我变你也变)

软件工程中耦合是指各个模块依赖程度,耦合越高,维护成本越高

为了便于维护,自然希望耦合越低越好。
?

解耦:

解除耦合,弱化两个东西之间的联系,减少互相之间互相影响。(我变你不变)

耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合

尽量做到高内聚,低耦合

对于我们 Android 开发者来说,常见的架构模式基本上就是 MVC,MVP,MVVM,这三种也是开发 GUI 应用程序常见的模式。
除此之外还有 分层模式,客户端-服务器模式(CS模式),主从模式,管道过滤器模式,事件总线模式 等等。

应用程序的数据为Model,用户界面的层次称为View

MV*(MVC/MVP/MVVM)就是实现了领域模型数据和UI层的解耦。

MVC、MVP、MVVM对其解耦的思路的不同。从历史的角度来看,MVC、MVP和MVVM是一种进化的关系

MVC(Model-View-Centre)的依赖关系

?定义三个接口 (数据、视图、控制)

interface IModel {

    /**
     * 绑定 view
     */
    fun setView(view:IView)

    /**
     * 数据模型 处理输入的数据
     */
    fun dataHandler(data:String)

    /**
     * 数据模型 清除数据
     */
    fun dataCleared()

}
interface IView {

    fun setController(controller:IController)

    /**
     * 数据处理中状态
     */
    fun dataHandlering()

    /**
     * 数据处理完成后 更新界面
     */
    fun onDataHandled(data:String)

}
/**
 * 控制器接口  定义控制器d逻辑
 */
interface IController {

    fun setModel(model:IModel)

    /**
     * 数据变化后 通知控制器
     */
    fun onDataChanged(data:String)

    /**
     * 清空按钮事件
     */
    fun clearData()

}

?分别实现IModel和IController

class CModel : IModel {

    private var view:IView? = null
    private var handler: Handler = Handler(Looper.getMainLooper())

    override fun setView(view: IView) {
       this.view = view
    }

    override fun dataHandler(data: String) {



        view?.dataHandlering()

        handler.removeCallbacksAndMessages(null)

        handler.postDelayed({

            if (TextUtils.isEmpty(data)){
                view?.onDataHandled("")

            }else {
                view?.onDataHandled("look:${data}")
            }
        },2000)
    }

    override fun dataCleared() {

        view?.onDataHandled("")
    }
}
class CController : IController {

    private var model:IModel? = null


    override fun setModel(model: IModel) {
        this.model = model
    }

    override fun onDataChanged(data: String) {

        model?.dataHandler(data)
    }

    override fun clearData() {
        model?.dataCleared()
    }
}

IView在 对应Activity中实现

class MainMvcActivity : AppCompatActivity(),IView {

    private var binding : ActivityMainBinding? = null

    private var controller:IController = CController()//创建 控制器
    private var model:IModel = CModel()//创建数据模型

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        controller.setModel(model)
        this.setController(controller)//持有控制器
        model.setView(this)//数据模型持有 view视图


        binding?.editTextTextEmailAddress!!.addTextChangedListener(object : TextWatcher{
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {


            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                controller.onDataChanged(s.toString())
            }

            override fun afterTextChanged(s: Editable?) {

            }
        })

        binding?.clear!!.setOnClickListener {

            controller.clearData()
        }


    }

    override fun setController(controller: IController) {

//        this.controller = controller

    }

    override fun dataHandlering() {

        binding?.textView!!.text = "正在加载数据......"
    }

    override fun onDataHandled(data: String) {

        if (TextUtils.isEmpty(data)){

            binding?.editTextTextEmailAddress!!.setText("")
            binding?.textView!!.text = "没有数据了"
        }else{

            binding?.textView!!.text = data

        }
    }
}

Ok完成!!!!

梳理一下:

请看IModel,IView,IController接口可以看到,View 持有 Controller,Controller持有 Model,Model 持有 View。这是MVC 的通信流程

再看?MainMvcActivity , binding?.clear 触发,通过 controller (controller.clearData()) 的clearData()方法,通知 Model(model?.dataHandler(data))执行?dataHandler(data)方法处理数据,处理完数据后 通过View (?onDataHandled(data:String)) 更新界面;

优点:

  1. 结构清晰,职责划分清晰
  2. 降低耦合
  3. 模块化程度高,有利于重用

缺点:

  1. 其实我们上述的示例,已经是经过优化的 MVC 结构了,一般来说,Activity / Fragment 会承担 View 和 Controller 两个角色,就会导致 Activity / Fragment 中代码较多
  2. Model 直接操作 View,View 的修改会导致 Controller 和 Model 都进行改动
  3. 增加了代码结构的复杂性
  4. Controller测试困难,视图同步操作是由View自己执行,而View只能在有UI的环境下运行。在没有UI环境下对Controller进行单元测试的时候,Controller业务逻辑的正确性是无法验证的:Controller更新Model的时候,无法对View的更新操作进行断言

MVP(Model View Presenter)

从MVC演化而来,控制逻辑,数据处理逻辑和界面交互耦合,同时能将 MVC 中的 View 和 Model 解耦控制逻辑,数据处理逻辑和界面交互耦合,同时能将 MVC 中的 View 和 Model 解耦

interface IModel {

    fun setPersenter(p:IPersenter)

    fun dataHeadler(data:String)

    fun detaClear()
}

interface IView {

    fun setPersenter(p:IPersenter)

    fun loading()

    fun showDate(data:String)
}

interface IPersenter {

    fun setModel(m:IModel)//绑定 model

    fun setView(v:IView)//绑定 view

    fun dataChange(data:String)//model 数据处理完

    fun dataCleared()//model 清除数据

    fun onTextChanged(data: String)//view 数据变化

    fun onBtnClicked()//view btn 清空数据
}

class PModel : IModel {

    private var persenter:IPersenter? = null
    private val handler : Handler = Handler(Looper.getMainLooper())
    override fun setPersenter(p: IPersenter) {
        this.persenter = p
    }

    override fun dataHeadler(data: String) {

        handler.removeCallbacksAndMessages(null)
        handler.postDelayed({

            if (TextUtils.isEmpty(data)){

                persenter?.dataChange("")
            }else{
                persenter?.dataChange("MVP : ${data}")
            }
        },2000)


    }

    override fun detaClear() {

        handler.removeCallbacksAndMessages(null)
        persenter?.dataCleared()
    }
}
class PPersenter : IPersenter {

    private var model:IModel? = null

    private var view:IView? = null

    override fun setModel(m: IModel) {
        this.model = m
    }

    override fun setView(v: IView) {
       this.view = v
    }

    override fun dataChange(data: String) {

        view?.showDate(data)

    }

    override fun dataCleared() {

        view?.showDate("")
    }

    override fun onTextChanged(data: String) {
        view?.loading()
        model?.dataHeadler(data)
    }

    override fun onBtnClicked() {
        model?.detaClear()

    }
class MainMvpActivity : AppCompatActivity() , IView{

    private  var binding:ActivityMainBinding? = null

    private var persenter:IPersenter? = null

    private var pPersenter:IPersenter = PPersenter()
    private var model:IModel = PModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        binding?.textView!!.text = "mvp"

        this.setPersenter(pPersenter)
        model.setPersenter(pPersenter)
        pPersenter.setModel(model)
        pPersenter.setView(this)

        binding?.editTextTextEmailAddress!!.addTextChangedListener(object:TextWatcher{

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {



            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                persenter?.onTextChanged(s.toString())
            }

            override fun afterTextChanged(s: Editable?) {

            }
        })

        binding?.clear!!.setOnClickListener {

            persenter?.onBtnClicked()
        }

    }

    override fun setPersenter(p: IPersenter) {
        this.persenter = p
    }

    override fun loading() {

        binding?.textView!!.text = "MVP正在加载...."
    }

    override fun showDate(data: String) {

        if (TextUtils.isEmpty(data)){

            binding?.editTextTextEmailAddress!!.setText("")
            binding?.textView!!.text =  "没有数据!"

        }else{

            binding?.textView!!.text =  data
        }

    }

操作流程:

view -- 》 persenter --》model --》persenter--》view

?Persenter 同时持有 Model和View,Model 和 View 单独持有Persenter。通过 Presenter 做中转

  1. 结构清晰,职责划分清晰
  2. 模块间充分解耦

缺点:

  1. 会引入大量的接口,导致项目文件数量激增
  2. 增大代码结构复杂性

更多了解:

Android官方MVP架构解读

官方MVP架构项目地址为:https://github.com/googlesamples/android-architecture.
?

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-08-07 12:23:20  更:2021-08-07 12:23:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 11:08:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码