Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 1)
『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率。 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则。
组件化设计的思路
不管是开发客户端应用程序还是开发服务器端应用程序,『组件』这个词我们并不陌生。不管是在iOS中的xib,还是在AngularJS的Component,或者后端开发的 User Control,可复用的组件是面向对象开发的基础。所以在Unity 3D 框架设计时,组件化是核心的概念。那么如何去设计SubView和SubViewModel,我总结出几条原则:
- 当一个功能被不同的场合频繁用到,建议将这个功能抽象成SubView(SubViewModel)
- SubView(SubViewModel)应该保持高内聚,低耦合原则
- SubViewModel不应该处理具体的业务逻辑,它很单纯,可通过委托Delegate的方式交由外部处理
构建SubView和SubViewModel
假设现在有如下一个需求,需要绑定角色的信息到头像上,如下图所示:

这是一个很常见的需求,创建一个MonoBehaviour,定义Public的变量并引用这些控件,最后再将这个MonoBehaviour附加到GameObject上,很快就能完成。当然,我不能说这样的实施是错误的,毕竟我们只要保证运行正确就可以了。
看到左上角的勋章吗,这个勋章会在不同的场景出现,我们优先把它考虑成一个SubView(BadgeView),也就是最外层的FaceBoxView里嵌套了一个BadgeView。
public class FaceBoxView:UnityGuiView<FaceBoxViewModel>
{
public Text nameText;
public Text levelText;
public Image faceImage;
public BadgeView badgeView;
}
我们在分析一下BadgeView需要什么数据?它需要武器的Icon和属性颜色,所以我们抽象出一个Badge的DataModel:
public class Badge
{
public string Icon { get; set; }
public string ElementColor { get; set; }
}
所以对于FaceBoxViewModel而言,它为FaceBoxView服务。FaceBoxView需要什么数据,它就提供什么数据。显然它需要提供Name,Level,Face以及Badge组件的DataModel:
public class FaceBoxViewModel:ViewModelBase
{
public readonly BindableProperty<string> Name=new BindableProperty<string>();
public readonly BindableProperty<int> Level=new BindableProperty<int>();
public readonly BindableProperty<string> Face=new BindableProperty<string>();
public readonly BindableProperty<Badge> Badge=new BindableProperty<Badge>();
public override void OnStartReveal()
{
base.OnStartReveal();
Initialization();
}
public void Initialization()
{
Name.Value = "比尔";
Level.Value = 9;
Face.Value = "Avatar204_Face";
Badge.Value = new Badge() {Icon = "Icon_WeaponRod", ElementColor = "1CB9FFFF"};
}
}
因为Badge是BindableProperty类型对象,特点是当Badge Value改变时,触发的OnValueChanged事件就可以给BadgeViewModel传递数据,从而初始化BadgeView:
protected override void OnInitialize()
{
base.OnInitialize();
Binder.Add<string>("Name",OnNamePropertyVlaueChanged);
Binder.Add<int>("Level",OnLevelPropertyValueChanged);
Binder.Add<string>("Face",OnFacePropertyValueChanged);
Binder.Add<Badge>("Badge",OnBadgePropertyValueChanged);
}
private void OnBadgePropertyValueChanged(Badge oldValue, Badge newValue)
{
badgeView.BindingContext = new BadgeViewModel() ;
badgeView.BindingContext.Initialization(newValue);
}
我们可以看到,组件化的实施从代码量上是变得复杂了,组件的颗粒度越细,那么嵌套的层次就越深,如果某个功能只出现一次,并且不会被复用,那么我不推荐将它变为一个SubView(SubViewModel)
小结
本文为大家介绍怎样将组件化模式思想引入到Unity 3D中,在我的uMVVM框架中,组件化是核心,就像用户控件一样,随拿随走,它们保持高度独立,这样的好处是不会产生紧耦合。还值得一提的是,其实Unity 3D本身的开发模式就是基于组件化开发的。只要创建一个MonoBehaviour组件然后附加到GameObject上就能正常运行。但需要注意的事,如果没有好的约束,一个GameObject上就会附加好多个MonoBehaviour,GameObject的子GameObject也会附加很多个MonoBehaviour,久而久之,整个层级结构会变得异常复杂和难以维护。uMVVM的理念是只需要一个View,View是唯一的入口,并且View可以是非常复杂,里面维护了所有的SubView,所以换UI也好,换功能也罢,只要关注于对应的View即可。
源代码托管在Github上,点击此了解
Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 1)的更多相关文章
- Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 1)
『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率. 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则. 组件化 ...
- Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 2)
在我们设计和开发应用程序时,经常要用到控件.比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件.属性可以更改它的外观,比如背景色,标题等, ...
- Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 2)
在我们设计和开发应用程序时,经常要用到控件.比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件.属性可以更改它的外观,比如背景色,标题等, ...
- 认证鉴权与API权限控制在微服务架构中的设计与实现(四)
引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的完结篇,前面三篇已经将认证鉴权与API权限控制的流程和主要细节讲解完.本文比较长,对这个系列进行收尾,主要内容包括 ...
- atitit.系统架构图 的设计 与工具 attilax总结
atitit.系统架构图 的设计 与工具 attilax总结 1. 架构图的4个版式(标准,(左右)悬挂1 2. 架构图的层次结构(下属,同事,助手)1 3. wps ppt1 4. 使用EDraw画 ...
- Java生鲜电商平台-App系统架构开发与设计
Java生鲜电商平台-App系统架构开发与设计 说明:阅读此文,你可以学习到以下的技术分享 1.Java生鲜电商平台-App架构设计经验谈:接口的设计2.Java生鲜电商平台-App架构设计经验谈:技 ...
- Java生鲜电商平台-商品基础业务架构设计-商品设计
Java生鲜电商平台-商品基础业务架构设计-商品设计 在生鲜电商的商品中心,在电子商务公司一般是后台管理商品的地方.在前端而言,是商家为了展示商品信息给用户的地方,它是承担了商品的数据,订单,营销活动 ...
- zz《分布式服务架构 原理、设计与实战》综合
这书以分布式微服务系统为主线,讲解了微服务架构设计.分布式一致性.性能优化等内容,并介绍了与微服务系统紧密联系的日志系统.全局调用链.容器化等. 还是一样,每一章摘抄一些自己觉得有用的内容,归纳整理, ...
- ABSD 基于架构的软件设计方法方法简介(摘抄)
ABSD(Architecture-Based Software Design)基于架构的软件设计方法 有三个基础: 第一个基础是功能分解.在功能分解中,ABSD方法使用已有的基于模块的内聚和耦合技术 ...
随机推荐
- Typescript中抽象类与接口详细对比与应用场景介绍
现如今,TS正在逐渐成为前端OO编程的不二之选,以下是我在学习过程中对抽象类和接口做的横向对比. 1. 抽象类当做父类,被继承.且抽象类的派生类的构造函数中必须调用super():接口可以当做“子类” ...
- Java中位运算符的使用
先预知识: 数据在计算机中是以二进制的形式进行存储的,而二进制在内存中是以补码的形式进行存储的.在介绍位运算之前,首先来看一下原码.反码和补码的概念.由于正数的原码.反码和补码的形式都是一样的,所以以 ...
- c++容器加迭代器和python装饰器的对比
c++利用对象实现简单数据的测试: class TestDataEmptyArray { public: static vector<int> get_array() { std::vec ...
- swap
添加交换分区 SWAP(交换)分区是一种通过在硬盘中预先划分一定的空间,然后将把内存中暂时不常用的数据临时存放到硬盘中,以便腾出物理内存空间让更活跃的程序服务来使用的技术,其设计目的是为了解决真实物理 ...
- SpringMVC(十一) RequestMapping获取Cookie值
可以在控制器方法中使用类似@CookieValue("JSESSIONID") String sessionID的方式,来获取请求中的Cookie的值. 样例控制器代码 packa ...
- Java笔记(五)泛型
泛型 一.基本概念和原理 泛型将接口的概念进一步延申,“泛型”的字面意思是广泛的类型. 类.接口和方法都可以应用于非常广泛的类型,代码与它们能够操作 的数据类型不再绑定到一起,同一套代码可以应用到多种 ...
- [PA2015]Rozstaw szyn
[PA2015]Rozstaw szyn 题目大意: 一棵\(n(n\le5\times10^5)\)个点的树,其中有\(m\)个结点是叶子结点.叶子结点权值已知,你可以自己决定其余结点的权值,定义整 ...
- [JOI2017/2018]美術展
[JOI2017/2018]美術展 题目大意: 有\(n(n\le5\times10^5)\)个物品,每个物品有两个属性:尺寸\(A_i\)和收益\(B_i\).从中选取一个子集,总收益为\(\sum ...
- BZOJ2670 : Almost
求出前缀和$s[]$,那么区间$[l,r]$的几乎平均数$=\frac{s[r]-s[l-1]}{r-l}$. 若只有一个询问,那么可以维护$(i,s[i-1])$的凸壳,在凸壳上二分点$(i,s[i ...
- windows安装并使用Anaconda
前言 本意是要使用Jupyter(Jupyter官网地址),在Jupyter官网上看到,强烈建议新手使用Anaconda,于是开始下载Anaconda使用.Anaconda是用于管理开源包(packa ...