MVC

概述

用户对view操作后,会将处理移交controller进行,controller会根据来自view的数据决定调用哪一个model的接口,然后由model执行相关的业务逻辑,当model变更之后,会通过观察者模式通知view,view获得变更消息之后,会向model请求新的数据,然后更新界面

关键点

  • view是把控制权移交给controller,controller执行应用程序先关的应用逻辑,即对来自view的数据进行预处理、决定调用哪个model的接口等
  • controller操作model,model执行业务逻辑对数据进行处理。但是不会直接操作view
  • view和model的同步消息是通过观察者模式进行的,而同步操作时由view自己请求model的数据然后对视图进行更新

数据流向在这里插入图片描述

  • controller->model:controller在收到用户的请求时会调用model里的方法来处理具体的业务逻辑
  • controller->view:controller会根据model的返回结果来进行路由跳转
  • model—>view:如果model里的数据发生变化便会通知view

这个数据流线图的input之所以指向controller是因为 在早期开发的web开发逻辑中是在浏览器中输入url 此时controller会接受url并且处理 最后返回给浏览器一个html界面

优点

  1. 将业务逻辑和展示逻辑分离,模块化程度高。且当应用逻辑变更时,只需要更换Controller即可,不需要变更业务逻辑和展示逻辑

缺点

  1. view和model之间存在耦合。view可能直接操作model,导致业务逻辑泄露
  2. 在大型项目中,Control层会变的非常臃肿,难以维护
  3. Control和view的联系紧密,不好进行单独测试
  4. view无法组件化。因为view强依赖特定的model

MVP

概述

和MVC一样,用户对view的操作也会移交给Presenter处理,然后model执行业务逻辑,但是model在变更之后,会通过观察者模式传递给Presenter而不是view。Presenter在获得到model变更的消息之后,通过view提供的接口更新界面

关键点

  • view不在负责同步的逻辑,而是由presenter负责。presenter中机油应用程序的逻辑也有同步逻辑
  • view需要提供更新操作界面数据的结构给presenter进行调用

数据流向

[图片]

  • input->view:用户通过view交互
  • presenter->view:presenter操作view提供的数据接口将数据直接推送给view
  • presenter->model:接收到用户操作时调用相应model处理业务逻辑
  • view->presenter:用户操作移交给presenter处理
  • model->presenter:完成业务逻辑的操作后将结果返回给presenter

手动实现了view和model数据的双向同步

优点

  1. view和model彻底解耦,通过接口与Presenter交互
  2. view可以组件化。在MVP中,view不依赖model,这样就可以让view从特定的环境中脱离出来

缺点

  1. 需要为view定义大量的更新接口来让Presenter调用
  2. UI的变更可能需要同时修改View和Presenter的实现

MVVM

概述

MVVM的调用关系和MVP一样,但是子啊MVP中有presenter负责的view和model之间的数据同步,在MVVM中全部交给框架完成,开发者自身不用关心

数据流向

[图片]

  • input->view:用户通过view交互
  • viewmodel->model:接收到用户操作时调用相应model处理业务逻辑
  • view->presenter:用户操作移交给viewmodel处理
  • model->viewmodel:完成业务逻辑的操作后将结果返回给viewmodel

在MVVM中,数据的双向同步由框架自身完成,开发者不用关心,viewmodel只用操作model,修改model中的数据,然后接受返回的数据更新自身即可,新的值会自动推送到view并更新显示

优点

  1. 开发者无需手动更新view,框架自动同步view和viewmodel的状态,大大提高了代码的可维护性
  2. UI与逻辑彻底分离,设计师可以专注于view,开发者可以专注于业务逻辑
  3. 简化测试,因为view跟着model变更,所以只要保证model正确,view就正确,减少了对view同步更新的测试

缺点

  1. 在简单项目中,强行使用MVVM会增加项目的复杂性
  2. 数据绑定的声明是指令的写在view的模版中,这些内容没有办法去debug

实践

分别使用MVC 和 MVVM完成一个简单的计数器demo

MVP和MVVM较为相似而且在MVP与ArkTs的响应式状态管理理念背道而驰 所以在这里不过多赘述

使用MVC架构

model层

class CountModel{
  public count: number = 0;
}

view层

@Entry
@Component
struct Index {
  @State model:CountModel = new CountModel()

  private controller: CountController = new CountController(this.model)

  build() {
    Column() {
      Text(this.model.count.toString())
        .fontSize(20)
      Row(){
        Button('增加')
          .onClick(()=>{
            this.controller.increment()
          })
        Button('减少')
          .onClick(()=>{
            this.controller.reset()
          })
      }
    }
    .height('100%')
    .width('100%')
  }
}

Controller层

class CountModel{
  public count: number = 0;

  setCount(val: number){
    this.count = val
  }

  getCount(){
    return this.count
  }
  
}

在MVC中 view会注册成为model的观察者 当model的数据变化时 model会通知view
而ArkTs有响应式状态管理,使用@State即可实现同样的效果

使用MVVM架构

model层

class CountModel{
  public count: number = 0;
}

view层

@Entry
@Component
struct Index {
  @State vm:CountViewModel = new CountViewModel()
  build() {
    Column() {
      Text(this.vm.count.toString())
        .fontSize(20)
      Row(){
        Button('增加')
          .onClick(()=>{
            this.vm.increment()
          })
        Button('减少')
          .onClick(()=>{
            this.vm.reset()
          })
      }
    }
    .height('100%')
    .width('100%')
  }
}

viewmodel层

class CountViewModel  {
  public count: number = 0
  public model: CountModel = new CountModel()
  increment(){
    this.model.count++
    this.count = this.model.count
  }
  reset(){
    this.model.count--
    this.count = this.model.count
  }

}

可以看到使用MVVM实现了View与Model的完全解耦 相比与MVC职责更加明确 业务逻辑都集中在viewmodel中 也增强了组件的复用性

参考

https://github.com/livoras/blog/issues/11

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐