Android

MVC&&MVP&&MVVM

2020-01-03  本文已影响0人  jxcyly1985

MVC && MVP && MVVM

[TOC]

概念

架构模式

也叫架构风格,一个架构模式描述软件系统里的基本的结构组织或纲要。架构模式提供一些呈先定义好的子系统,指定它们的责任,并给出把它们组织在一起的法则和指南。一个架构模式常常可以分解成很多个设计模式的联合使用。MVC模式就属于架构模式。[7]

关键词

业务逻辑[8]

业务逻辑是业务领域的逻辑,是提供业务服务的规则和流程

业务逻辑包括

应用逻辑

应用逻辑是指视图和业务协作的一套机制

应用逻辑包括

关注点分离

在讨论这几种架构模式之前,我们先讨论一个关注点分离的设计原则。

关注点分离 (Separation of concerns,SOC)是对只与「特定概念、目标」(关注点)相关联的软件组成部分进行「标识、 封装和操纵」的能力,即标识、封装和操纵关注点的能力。 是处理复杂性的一个原则。 由于关注点混杂在一起会导致复杂性大大增加,所以能够把不同的关注点分离开来,分别处理就是处理复杂性的一个原则,一种方法。[1]

从关注点分离的定义我们可以关注到有四个关键词:

从分离点关注的概念和关键词描述,可以映射到我们日常的一些软件设计方法,例如:

分层设计这种架构风格是关注点分离的一种实施例子,因此分层设计满足关注点分离原则,那我们对应上面说的四个词来阐述对于这几种架构模式的理解,以及如何影响软件的质量。

MVC

MVC 关注点分离出三个要素

下图是组件之间的交互[3]

MVC协作

figure [1]

职责说明

基于上图的交互,我们对MVC各个组件的职责进行一下说明

在说职责之前,我们先想一下如何划分职责,可以达到职责单一,并且可以提高软件的复用性和可维护性。

View

在这里我想说下win32程序窗口创建的代码[4]

步骤:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC hdc;
   TCHAR greeting[] = _T("Hello, Windows desktop!");

   switch (message)
   {
   case WM_PAINT:
      hdc = BeginPaint(hWnd, &ps);

      // Here your application is laid out.
      // For this introduction, we just print out "Hello, Windows desktop!"
      // in the top left corner.
      TextOut(hdc,
         5, 5,
         greeting, _tcslen(greeting));
      // End application specific layout section.

      EndPaint(hWnd, &ps);
      break;
   case WM_DESTROY:
      PostQuitMessage(0);
      break;
   default:
      return DefWindowProc(hWnd, message, wParam, lParam);
      break;
   }

   return 0;
}

该代码是一个回调方法,用户提供给系统通知窗口相关的事件,这个和Android设置一个回调类似,不同的事,窗口事件包括了用户的指令(点击)和窗口本身的内部事件(绘制,销毁等)

如果不做任何代码的优化,在一个复杂的用户界面,这个函数会变的异常庞大,考虑到很多的业务逻辑是可以复用的,因此会提取业务相关的指令汇集到一个集中的处理。

这样的话,WndProc会出现一些变化,那假设我们理解的MVC各个组件职责如下图

WndProc职责抽离

Figure 2

Controller && Model

根据软件架构设计的分层[5]介绍的四层模型,核心是问题领域层,问题领域层对应业务实体层和业务逻辑层。

分层模型

Figure 3

按照分层设计,我们假设Controller对应问题领域层,那么Controller将变成整个软件的核心层,Controller内部将包含业务实体和业务逻辑。

按照这个定位,那么Model就会成为职责单一的数据管理层,那么不同的 Model可以对不同的数据源进行管理,

例如,数据库数据源,本地文件数据源,网络数据源,以及不同源的组合源

被动MVC && 主动MVC

如果Model不承担通知视图更新的职责,由Controller负责通知更新,那么就是被动MVC模式

如果由Model承担通知视图更新的职责,是主动MVC模式

从实际操作,我倾向于被动MVC模式,这样可以提升View渲染的性能,而不需要经过Model层操作之后进行View渲染。

在实现中,需要注意数据一致性的问题。

例如信息流场景,回看历史数据的时候,如果之前Model持久出现异常,没有一直合适的机制进行处理,则会导致中间丢失部分数据,前后浏览的记录会不一致。

效果

按照上面的设计,会带来一些设计的效果

figure [1]中的协作关系从软件设计上反映

MVC结构

Figure 4[被动MVC模式]

  1. Controller是一个策略,通过配置不同的Controller,对View的请求定制不同的响应
  2. View是一个观察者策略,和Controller进行解耦
  3. Controller也可以配置不同的Model,使用不同的数据管理
  4. 不同层有不同的数据抽象,使用不同的数据模型
  5. View不能直接访问Model,这样会破坏组件间的相互独立

MVC 本质上是通过分层的思想,使Controller,View,Model三个组件相互独立,支持View视图的灵活变化,以及Controller的配置改变数据层和业务规则。

Controller [假设]

业务逻辑层,负责业务逻辑的处理

Model [假设]

数据管理层,负责数据的获取

问题

按照上面的分析,以及各个组件的职责,的确可以达到重用Model,View的目的,同时Controller可以对不同的数据源,视图进行配置,灵活的满足客户需求。

但是这样Controller会显得过于庞大,我们实际只分离出了数据管理层,并没有对WndProc中各种业务处理进行分离,那是否我们可以配置多个Controller对应不同的M,这样Controller的就变成更简洁,职能更单一。

答案是应该这么做,并且可以提高Controller的复用性。

但是我们刚刚说到应用逻辑,监督和协调整个应用的活动。

如果Controller管理View以及Model之间的协作关系,同时Controller又具有业务的功能,那么对于Controller的职责来说是不单一的,因此我们需要重新定位Controller和Model的职责。

MVC职责修正

Figure 2 [修正]

那承担数据管理职责的层,对应数据的持久化的工作,则属于基础设施层,Model应该是包括业务逻辑的要素(领域实体,规则,约束),业务服务提供业务流程的协作管理。

MVC_修正

Figure 3[修正]

Controller

应用逻辑组件

连接视图和业务,控制程序的流程

Model

业务逻辑组件

用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法

Model层涉及的业务逻辑元素较多,其内部可以分离出数据访问层,用于抽象业务数据的获取,包括本地数据和远程数据的获取,目标是屏蔽掉数据访问的细节,例如数据库的连接,数据的存储过程细节,服务器接口协议以及解析过程。

核心

MVP

通过MVC的分析,如果按照**Figure 4 **的交互关系,本质上和MVP是没有区别的只是把

Controller -> Presenter

Presenter的职责和Controller职责是完全一样的。

MVP是MVVM实施的一种特例。

MVP结构

Figure 5

MVC&& MVP区别

说到这里回到MVC 效果第5点

通常的谈到MVC和MVP的区别的时候,能否从View直接访问Model是一个区别的特征。

但是这个不是MVC必须的,很大的原因是因为MVC架构的框架实现导致这种理解。

因此我认为讨论View是否直接访问Model的优缺点更有意义。

View是否直接访问Model优缺点

职责

View

职责上和MVC的View没有区别,对比MVC的View,没有给出明确的实现规范,MVP比较明确的提出了接口方式的抽象

Presenter

负责应用逻辑处理,和对视图的更新

Model

提供业务逻辑服务

Model需要提供对Presenter的数据更新没有具体的实现要求,可以通过回调,观察者去实现,但是Model需要实现相应的回传机制,把值变化返回给到Presenter,对应Model来说,Presenter是解耦的,保持Model的独立性

优点

缺点

核心

MVVM

介绍MVVM之前,我们先介绍一下

双向绑定

双向绑定是指视图和模型之前的动态互动关系,当模型发生变化时,视图能更新;同时当视图发生变化时候,模型也随之更新,这种双向的互动机制,就是双向绑定。

MVVM结构

Figure 6

职责

MVVM本质上和MVP也没有本质的区别,但是View和ViewModel之间使用了双向绑定,其实是为了解决MVP模式中需要手动同步Model->Presenter->View,View->Presenter->Model的手动代码编写,在MVVM架构风格提供的框架中自动的完成了。

View

对比MVP方式,通过视图绑定解耦了View的具体实现,同时通过数据的统一抽象框架,不需要再单独去编写View视图的对外接口,减少了开发的工作量。

同时基于数据抽象的方式,降低了业务对视图的敏感性。

ViewModel

提供了双向绑定的实现机制提供应用逻辑服务

Model

提供业务逻辑服务,Model通过可被观察的数据,直接实现了Model到ViewModel的数据返回,这样可以不用在Model内部维护一套数据更新的机制,通过统一的可观察的数据对象,达到数据的更新通知。

也就是交互图的Model->ViewModel的notify操作,不是必须的,如果使用可观察的对象,对可观察对象的修改,自动就会传递到视图层

优点

缺点

核心

可参考官方提供的指导例子应用架构指南

总结

MVC,MVP,MVVM都是在MV*模式上的改进,本质上是一样,只是在组织的法则和指南上,即协作方式进行了不同的设计,以适用不同的场景,和减少开发人员的工作量。

同时也有相应的优缺点,新的改良都必须满足之前模式的核心内容。

因为本质上一样,基于场景来说,只能说通常开发使用,基于大部分人对MV*的理解来说

共性

不能解决的问题

上面说了使用架构模式通过关注点分离,实现了不同层的关注,但是架构模式本身解决不了子系统内部的问题,例如业务之间的抽象。

参考

[1] https://zh.wikipedia.org/zh/%E5%85%B3%E6%B3%A8%E7%82%B9%E5%88%86%E7%A6%BB 关注点分离

[2]http://aspiringcraftsman.com/2008/01/03/art-of-separation-of-concerns/ 关注点分离的艺术

[3]https://zh.wikipedia.org/wiki/MVC MVC模式

[4]https://docs.microsoft.com/zh-cn/cpp/windows/walkthrough-creating-windows-desktop-applications-cpp?view=vs-2019 演练:创建传统的 Windows 桌面应用程序

[5]《软件架构设计》第二版 温昱 第13章《如何分层》

[6]https://developer.android.com/jetpack/docs/guide 应用架构指南

[7] https://baike.baidu.com/item/架构模式/9283553?fr=aladdin 架构模式

[8]https://www.cnblogs.com/kaisadadi/p/9265127.html 细说业务逻辑

上一篇下一篇

猜你喜欢

热点阅读