美文网首页
界面响应逻辑常用设计模式

界面响应逻辑常用设计模式

作者: 离原春草 | 来源:发表于2022-04-08 12:55 被阅读0次

游戏开发中一块必不可少的模块就是游戏界面(User Interface,俗称UI)的制作,即UI在接收到用户的输入之后,如何进行响应的问题,这个问题我们称之为UI交互逻辑的实现(当然,下面的这些设计模式其实不仅仅局限于游戏UI,一些常见的应用场景甚至包括网页交互、应用UI交互、前后台交互)。

UI交互逻辑在实践中的复杂度远比上面一句话描述的要高,主要需要解决如下的一些问题:

  • 如何保证整体的交互逻辑清晰、简洁、易维护
  • 如何保证多个关联UI之间的响应逻辑能够实现很好的分离与解耦
  • 如何做到职责分离,将展示的相关逻辑与底层的数据逻辑做到很好的隔离

而在长期的实践过程中,UI交互逻辑积累了一些成熟易用的设计模式,下面来对这些设计模式的具体方案以及优缺点进行叙述与对比分析。

1. Model View Controller(MVC)

MVC模式将整个交互逻辑分为三个部分,即Model,View以及Controller:

  • Model对应的是整个交互逻辑中的底层数据,负责整个系统的数据表达以及底层系统的交互逻辑(这里的交互逻辑是指应用层面的相关逻辑,而非UI交互界面的相关逻辑),这个部分的数据跟UI是完全解耦的
  • View对应的是整个交互逻辑中的上层视角,负责整个系统的视觉表现,比如游戏界面中与单个界面关联的Class就可以看成是一个View,最简单的示例就是与一个按钮关联的Class,需要注意的是,同一个Model可以对应于不同的View(当然也就对应于不同的Controller,在MVC模式中,View跟Controller通常是成双成对的),用通俗的话来解释就是,同样一份数据可以有不同的表达形式,比如可以用表格来表示,也可以用曲线来表示。
  • Controller对应的是整个交互逻辑的具体实施细节,负责链接Model跟View,将Model中的数据反应到View上面,接收到View上的相关输入并将之翻译成Model中的数据变动

整个逻辑Working Flow可以用下图表示:

相关的交互逻辑用文字表达如下:

  • Model负责管理整个应用的数据,包括业务逻辑的处理与存储,数据更新等。Model只从Controller处接收用户的输入;Model的数据变化不需要通过Controller转发给View,而是通过观察者模式,自动转达到View上。
  • View负责将Model用一种用户可以直观感受的方式绘制或者展示出来,可以理解为展示给用户的界面相关的逻辑代码
  • Controller负责从View处接收到用户的输入事件,经过有效性验证后根据不同的事件类型转达至Model处,完成对Model的调整与修改。由于Controller对View的实现不需要关心,只需要进行被动转发,因此一个Controller可以对应多个View

MVC中的交互流程有两种模式:

  • 第一种模式中,用户的输入直接作用在View上,通过View->Controller->Model的方式完成整个交互链路,如下图所示:
  • 第二种模式中,用户的输入通过某种其他方式直接作用在Controller上,比如系统应用检测到其他的数据变动之后直接调用Controller上的相关接口,完成Controller->Model->View的交互链路,如下图所示,需要注意的是,在这种模式下,Model的数据变化会通过调用View的接口完成数据到View的同步(通常是通过observe+listener的方式实现):

observer同步模式实现model到view更新的好处在于,如果有多个view同时指向同一个model,不过分别负责model的不同部分,那么在某个view更新了自己负责的model部分之后,另外的view在observer的模式下不需要进行更新响应;而如果我们使用更为直接的flow同步模式,在model发生变化的时候发起对所有的controller的相应接口的调用,就会变得浪费。

不过observer同步模式的不足之处在于代码跳转逻辑隐藏比较深,在追查bug的时候效率会比较低。

总结来说,MVC有如下的一些优点:

  • 很好的实现了View跟Model的分离,业务逻辑全放在Controller中,具有较高的模块化程度,当业务逻辑发生变化时,不需要改动View跟Model,只需要调整Controller即可
  • 将用户响应逻辑分解成了Controller跟View两个部分,前者负责根据用户的输入完成相应的交互逻辑,后者负责将底层的应用数据以直观地方式展示给用户,Controller不会直接改动到View,Controller到View的通信需要通过Model来完成
  • 支持多个View绑定到同一个Model中(比如通过观察者模式进行监听),且保持多个View之间的响应是相互独立互不干扰的

其缺点为:

  • 因为View的同步是根据观察者模式进行监听的,而View只能在有UI的环境下运行,因此单元测试以及调试较为困难
  • View是与Model关联的,对于不同的Model而言,View很难做到复用

2. Model View Presenter(MVP)

MVP其实就是在MVC的基础上将Controller替换成Presenter,是MVC的一个变种,其整体的Working Flow可以用下图表示:

在MVP模式中,Presenter发挥的是”中间人“的作用,所有展示(presentation)相关的逻辑(即将Model的数据变动反应在View上的相关逻辑)都会交由Presenter来完成(不论是从Model到View,还是反过来,都是如此),也就是说,Model跟View之间不再发生任何的交互,而这正是MVP跟MVC的关键区别。

MVP模式下,用户的操作以及后续的触发逻辑可以用如下的流程示意图说明:

在MVP模式中,有多种实现方案:

  • 一个极端也是最常用的模式就是采用Passive View模式,在这种模式中,View只用作一个转发器,是一个非常轻量的Class,没有任何主动的逻辑,都是在响应用户与Controller的输入,这也是为什么叫Passive View的原因。
  • Supervising Controller模式,在这个模式下,Presenter会将一部分简单的逻辑放在View中,一些复杂的高层次的逻辑还是放在Presenter中,因此可以认为是一种监督式的Controller模式,在实际工作中,这种模式使用较少

Passive View模式下,View在接收到用户输入后,通过一个方法调用Presenter的对应方法进行响应,完成对Model数据的更新,并根据更新后的Model数据完成对View的修正;在View的初始化逻辑中,可以同步创建一个对应的Presenter,后续的所有逻辑都交由Presenter进行响应,下面给出一份C#示例代码:

public class DomainView : IDomainView
{
    private IDomainPresenter _domainPresenter = null;

    /// <summary>Constructor.</summary>
    public DomainView()
    {
        _domainPresenter = new ConcreteDomainPresenter(this);
    }
}

前面说过,View到Model的调用是通过Presenter完成的,这种调用转达通常是通过View持有Presenter完成的,而后面Model数据的变化通知给Presenter通常是通过observer模式实现,而Presenter调用View的相关接口进行更新则通常是需要Presenter持有View的成员变量,也就是说,View跟Presenter通常是相互持有的。

MVP的优点有:

  • V跟M分离,降低耦合,且由于View不需要关心Model的数据,因此可以实现View的重用
  • 模块职责划分更为明确,增强代码可读性
  • Presenter可以被多个View所共用,因为View的变化比Model变化频率高,通过这种方式可以有效增强代码复用能力
  • 对视图而言,隐藏了数据,简化了View的逻辑
  • 由于主要的功能逻辑已经都放在Presenter中,不需要依赖于View了,所以可以更好的进行单元测试

MVP的缺点有:

  • View跟Presenter之间的交互过于频繁
  • View跟Model的数据同步需要手写逻辑实现,当View较为复杂时,开发成本与维护成本都会上升
  • 一些复杂的View中会导致Presenter过于臃肿

对于一些复杂的View来说,为了减轻Presenter的负担,可以在Presenter跟View之间增加Mediator,在Presenter跟Model之间增加Proxy:

MVC与MVP的区别点有:

  • View跟Model不再直接交互,而是通过Presenter完成交互逻辑
  • View跟Presenter通常是一一对应,但是一些复杂的View可能需要多个Presenter来进行承接(所有的复杂逻辑都放在Presenter中,如果View过于复杂就会导致Presenter的臃肿,为了瘦身增效,可以考虑将之拆分成多个Presenter),而MVC中,Controller可以被多个View所共享,且Controller可以通知哪些View可以被显示出来

3. Model View View-Model(MVVM)

在MVP模式中,View跟Model的变动是通过View与Presenter的接口调用实现的,当需要处理的UI元素不断增加,需要处理的Model数据不断增加,就会导致相应的处理接口数目不断增加,导致开发与维护成本上升。为了解决这个问题,MVVM通过View-Model完成View跟Model之间的双向绑定(这个逻辑通过一个叫做binder的东西实现),从而在两者任何一方发生变化的时候,都能自动完成另一方的数据转达通知与同步,避免了手写大量同步代码的低效。

MVVM的流程示意图给出如下:

这是一种从MVP模式中演变过来的设计模式,从上图看来,MVVM跟MVP没有太大区别,但实际上我们前面说过,MVP中V跟P是相互持有来实现数据同步的,而在MVVM中,两者(View跟ViewModel)的关联与同步则是通过DataBinding实现(这种binding可以通过反射或者其他的方式来自动完成,降低手写代码的复杂度),具体而言,就是View跟View-Model通过双向绑定(即View-Model的变化会反映到View上,而View的变化也会反映到View-Model上,这个绑定通常是通过观察者模式完成)实现了View跟View-Model数据的自动同步,避免了人为的干涉以及开发者对于View/Model之间复杂数据同步之间的关注:

  • View-Model负责监测Model的变化,并根据变化对View进行更新,在实现上,这一步可以通过事件监听或者Data Binding完成(如DataChangeNotify)
  • View-Model负责监听View的变化,并将View的变动反映到Model上,在实现上,这个通常是通过事件监听完成

MVVM的优点在于:

  • 除了Model可以继承MVC/MVP的可复用性之外,在部分情况下,View-Model也可以被复用
  • 通过数据绑定实现了Model跟View的自动关联,Model跟View无需编写过于复杂的更新逻辑,所有的更新同步统一在View-Model中完成
  • 数据同步逻辑通过双向绑定实现,可以保证View的代码简洁

MVVM的缺点在于:

  • 数据绑定使得调试变得困难
  • 数据绑定导致代码重用较为困难
  • 如果Model较大会使得数据的释放存在困难,从而导致内存消耗增加

另外,值得一提的是,MVC/MVP/MVVM三种模式中,由于都增加了中间用于同步的转发层,因此Model数据不必来自于同一个Class,甚至于同一个中间转发层可以被多个View所共享。

总结

MVC起于草莽,引入了分层概念,不过Model跟View之间还是存在耦合,维护起来存在困难。
MVP在MVC的基础上做了进一步的解耦,隔离了Model跟View之间的交互,不过Model跟View之间的数据同步需要手动添加接口实现,开发与维护成本较高。
MVVM在MVP的基础上引入了双向绑定机制,使得Model跟View的同步可以自动完成,从而解放了开发者的双手,提升了开发的效率。

MVP跟MVVM完全隔绝了Model跟View,所有的同步都是通过中间层经过拷贝进行转达,不过有时候有些数据拷贝的开销太大,可能也会考虑打破View跟Model的界限,完成两者的直接同步,也就是说,在实践中,我们会发现,有时候模式并不是完全清晰的,而是多种方案混杂一炉的。

上面给出的MVC、MVP以及MVVM是狭义下的设计模式,从广义上来说,因为MVC模式就是实现Model跟View的分离,因此三者都可以归纳在MVC模式下。

参考

[1]. 谈谈MVC模式
[2]. MVC,MVP 和 MVVM 的图示
[3]. Model–view–controller
[4]. Model–view–presenter
[5]. Model–view–view model
[6]. GUI Architectures
[7]. MVVM 介绍
[8]. MVVM模式理解
[9]. MVC,MVP 和 MVVM 模式如何选择?
[10]. Android高精战争(MVC、MVP、MVVM)
[11]. MVC、MVP、MVVM的区别及联系

相关文章

  • 界面响应逻辑常用设计模式

    游戏开发中一块必不可少的模块就是游戏界面(User Interface,俗称UI)的制作,即UI在接收到用户的输入...

  • 《界面设计模式》读书笔记

    模式意味着重用,这是《界面设计模式》想要传达给我们读者的思想核心。所以整本书收集了很多常用的界面设计模式,如何组织...

  • MVC、MVP与ListView、RecycleView

    1.设计模式(mvc, mvp) (1)mvc 将数据模型、界面视图和业务逻辑控制分开的模式 Model :只准...

  • 语音用户界面设计

    一、发展历程 从IVR——智能音箱——多模态界面 二、语音界面设计中常用规则 1、命令——控制/对话模式 2、确认...

  • SpringMVC快速入门

    什么是MVC设计模式? Controller:负责接收并处理请求,响应客户端。 Model:模型数据,业务逻辑。 ...

  • 从ES6重新认识JavaScript设计模式(二): 工厂模式

    1 什么是工厂模式? 工厂模式是用来创建对象的一种最常用的设计模式。我们不暴露创建对象的具体逻辑,而是将将逻辑封装...

  • 响应式用户界面与设计模式

    这本书很多翻译都很奇怪,建议还是直接看英文单词是怎么一回事 cha4 探索Android平台 安卓是开放的,对于每...

  • SpringMVC 入门和RESTful风格概述

    MVC设计模式 controller:负责接收并处理请求,响应客户端Model:处理具体的业务逻辑,产生不同的模型...

  • Java设计模式之简单工厂模式

    工厂模式是Java中很常用的设计模式之一,主要用来提供一种创建对象的方式,在该设计模式中,创建对象的逻辑不会暴露给...

  • Java 常用设计模式简例

    简述Java常用设计模式 简述Java常用设计模式及设计原则 strate---------策略模式针对接口编程,...

网友评论

      本文标题:界面响应逻辑常用设计模式

      本文链接:https://www.haomeiwen.com/subject/kmossrtx.html