博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 2)
阅读量:7219 次
发布时间:2019-06-29

本文共 3056 字,大约阅读时间需要 10 分钟。

阅读目录

在我们设计和开发应用程序时,经常要用到控件。比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件。属性可以更改它的外观,比如背景色,标题等,而事件可以丰富控件的行为,比如最常见的『按钮点击』,谁也不能确定点击之后将发生什么事,是连接数据库呢还是弹出警告框,在不同的场景下,『按钮点击』 的行为往往呈现不一致。所以,与其举棋不定,还不如把处理委托给开发者,这就是『OnClick』事件。

SubView行为多变性

在上篇文章中,我阐述了为什么要使用SubView,总结起来就3个字:『可复用』 。那么问题来了,既然是可复用,那就意味着SubView可以在任何场景下使用,那怎样才能确保它做的是正确的行为呢?

举个栗子,还是 以如下图FaceBox为例,不同的场景下点击头像应该处理不同的事:

o_facebox.png

  • 在战团中点击头像,则显示该成员的具体信息
  • 在队伍里点击头像,则进入换人界面
  • 在战斗时点击头像,则显示它配置的战术

你看,同样一个SubView,在不同的场景下它的行为往往是不一致的。那我们怎么去跟踪这些行为呢?

定制SubView的行为

你可能会以如下方式去定制SubView的行为:

void OnClick(){    if(战团){        显示该成员的具体信息    }else if(队伍){        进入换人界面    }else if(战斗){        显示它配置的战术    }else{        //其他    }}

还是那句话这样,这样并没有错,甚至对某些SubView而言逻辑还很清晰。但仔细想想,这是最好的实践吗?

  • 如果我要继续添加一种情况,是不是只能在else if扩展,违反了开闭原则,应该对扩展是开放的,对修改是关闭的
  • 既然这个SubView是可复用的,那意味着将它放在任何项目中都是没问题的,但实际上OnClick里面处理了业务逻辑,紧耦合当前游戏的业务

所以显然上述代码不是最佳实践。那我们应该怎样去解决呢?

实际从开头的引言我已经提出了解决方案,以事件的形式委托给开发者来确定。一个Button也好,还是一个SubView也好,他们都是可复用的组件,不应该与具体的业务逻辑相结合。通过事件或者委托的形式,暴露给开发者来决定究竟要处理什么逻辑,这样才能和具体业务逻辑解耦。

委托的介入

还是以FaceBox举例,那么从上面的分析得出结论,我们需要定义委托或者事件,那应该定义在FaceBoxView呢还是FaceBoxViewModel中呢?

还是那句话,View不处理具体的业务逻辑,View将请求交给ViewModel去处理。

故在FaceBoxViewModel中增加可被外界监听的委托或者事件,我以委托举例,实际上事件就是特殊的委托。

public class FaceBoxViewModel:ViewModelBase{    //省略部分代码       public delegate void OnBeginDragHandler();    public OnBeginDragHandler OnBeginDrag;    public delegate void OnDragHandler();    public OnDragHandler OnDrag;    public delegate void OnEndDragHandler();    public OnEndDragHandler OnEndDrag;    public delegate void OnClickHandler();    public OnClickHandler OnClick;    //省略部分代码}

FaceBoxView不处理具体的逻辑,交由FaceBoxViewModel去实现:

protected override void OnInitialize(){    //省略部分代码    //监听事件    var beginDragEntry = new EventTrigger.Entry();    beginDragEntry.eventID = EventTriggerType.BeginDrag;    beginDragEntry.callback.AddListener(eventData => { OnBeginDrag(); });    eventTrigger.triggers.Add(beginDragEntry);    var dragEntry = new EventTrigger.Entry();    dragEntry.eventID = EventTriggerType.Drag;    dragEntry.callback.AddListener(eventData => { OnDrag(); });    eventTrigger.triggers.Add(dragEntry);    var endDragEntry = new EventTrigger.Entry();    endDragEntry.eventID = EventTriggerType.EndDrag;    endDragEntry.callback.AddListener(eventData => { OnEndDrag(); });    eventTrigger.triggers.Add(endDragEntry);    var pointClickEntry = new EventTrigger.Entry();    pointClickEntry.eventID = EventTriggerType.PointerClick;    pointClickEntry.callback.AddListener(eventData => { OnClick(); });    eventTrigger.triggers.Add(pointClickEntry);}private void OnClick(){    if (BindingContext.OnClick != null)    {        BindingContext.OnClick();    }}

脑海里梳理一下请求的流程:FaceBoxView.PointClick->FaceBoxViewModel.OnClick()->委托给外部的某个Handler。

小结

实际上『委托』这个概念非常重要,和具体的语言、平台无关。比如在iOS开发经常听到代理模式,顾名思义,将请求交给具体的处理者去处理。设计模式并不深奥,很多模式的理念都是相通的,不同的是对应语言下不同的表现形态,善于剖开现象看本质,很多都是相通的。

源代码托管在Github上,

本博客为 原创,基于 发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 (包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
分类: ,
本文转自木宛城主博客园博客,原文链接:http://www.cnblogs.com/OceanEyes/p/set_up_subview_and_subviewmodel_part2.html,如需转载请自行联系原作者
你可能感兴趣的文章
【iOS】Objective-C简约而不简单的单例模式
查看>>
Java实现扫码二维码登录
查看>>
python之字符串的操作和使用
查看>>
eclipse搭建ssm框架
查看>>
CSS div阴影效果
查看>>
显示所有SAP图标的ABAP代码
查看>>
group by 与 order by 一起使用的时候
查看>>
HTML+CSS
查看>>
链接服务器创建
查看>>
用Vue的方式实现复选框
查看>>
mac下安装xampp、及其之上的组件安装
查看>>
C++内存对齐总结
查看>>
Web设计的速查卡(转)
查看>>
数据结构之哈夫曼树
查看>>
hdu1038
查看>>
CentOS 6.4下Zabbix的安装配置
查看>>
前端开发注意的问题 ,浏览器兼容性
查看>>
centos和redhat下 uwsgi配置
查看>>
Markdown 学习笔记
查看>>
vue-element-admin 多层路由问题
查看>>