『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率。 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则。

组件化设计的思路

不管是开发客户端应用程序还是开发服务器端应用程序,『组件』这个词我们并不陌生。不管是在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)的更多相关文章

  1. Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 1)

    『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率. 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则. 组件化 ...

  2. Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 2)

    在我们设计和开发应用程序时,经常要用到控件.比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件.属性可以更改它的外观,比如背景色,标题等, ...

  3. Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 2)

    在我们设计和开发应用程序时,经常要用到控件.比如开发一个客户端WinForm应用程序时,微软就为我们提供了若干控件,这些控件为我们提供了可被定制的属性和事件.属性可以更改它的外观,比如背景色,标题等, ...

  4. 认证鉴权与API权限控制在微服务架构中的设计与实现(四)

    引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的完结篇,前面三篇已经将认证鉴权与API权限控制的流程和主要细节讲解完.本文比较长,对这个系列进行收尾,主要内容包括 ...

  5. atitit.系统架构图 的设计 与工具 attilax总结

    atitit.系统架构图 的设计 与工具 attilax总结 1. 架构图的4个版式(标准,(左右)悬挂1 2. 架构图的层次结构(下属,同事,助手)1 3. wps ppt1 4. 使用EDraw画 ...

  6. Java生鲜电商平台-App系统架构开发与设计

    Java生鲜电商平台-App系统架构开发与设计 说明:阅读此文,你可以学习到以下的技术分享 1.Java生鲜电商平台-App架构设计经验谈:接口的设计2.Java生鲜电商平台-App架构设计经验谈:技 ...

  7. Java生鲜电商平台-商品基础业务架构设计-商品设计

    Java生鲜电商平台-商品基础业务架构设计-商品设计 在生鲜电商的商品中心,在电子商务公司一般是后台管理商品的地方.在前端而言,是商家为了展示商品信息给用户的地方,它是承担了商品的数据,订单,营销活动 ...

  8. zz《分布式服务架构 原理、设计与实战》综合

    这书以分布式微服务系统为主线,讲解了微服务架构设计.分布式一致性.性能优化等内容,并介绍了与微服务系统紧密联系的日志系统.全局调用链.容器化等. 还是一样,每一章摘抄一些自己觉得有用的内容,归纳整理, ...

  9. ABSD 基于架构的软件设计方法方法简介(摘抄)

    ABSD(Architecture-Based Software Design)基于架构的软件设计方法 有三个基础: 第一个基础是功能分解.在功能分解中,ABSD方法使用已有的基于模块的内聚和耦合技术 ...

随机推荐

  1. Typescript中抽象类与接口详细对比与应用场景介绍

    现如今,TS正在逐渐成为前端OO编程的不二之选,以下是我在学习过程中对抽象类和接口做的横向对比. 1. 抽象类当做父类,被继承.且抽象类的派生类的构造函数中必须调用super():接口可以当做“子类” ...

  2. Java中位运算符的使用

    先预知识: 数据在计算机中是以二进制的形式进行存储的,而二进制在内存中是以补码的形式进行存储的.在介绍位运算之前,首先来看一下原码.反码和补码的概念.由于正数的原码.反码和补码的形式都是一样的,所以以 ...

  3. c++容器加迭代器和python装饰器的对比

    c++利用对象实现简单数据的测试: class TestDataEmptyArray { public: static vector<int> get_array() { std::vec ...

  4. swap

    添加交换分区 SWAP(交换)分区是一种通过在硬盘中预先划分一定的空间,然后将把内存中暂时不常用的数据临时存放到硬盘中,以便腾出物理内存空间让更活跃的程序服务来使用的技术,其设计目的是为了解决真实物理 ...

  5. SpringMVC(十一) RequestMapping获取Cookie值

    可以在控制器方法中使用类似@CookieValue("JSESSIONID") String sessionID的方式,来获取请求中的Cookie的值. 样例控制器代码 packa ...

  6. Java笔记(五)泛型

    泛型 一.基本概念和原理 泛型将接口的概念进一步延申,“泛型”的字面意思是广泛的类型. 类.接口和方法都可以应用于非常广泛的类型,代码与它们能够操作 的数据类型不再绑定到一起,同一套代码可以应用到多种 ...

  7. [PA2015]Rozstaw szyn

    [PA2015]Rozstaw szyn 题目大意: 一棵\(n(n\le5\times10^5)\)个点的树,其中有\(m\)个结点是叶子结点.叶子结点权值已知,你可以自己决定其余结点的权值,定义整 ...

  8. [JOI2017/2018]美術展

    [JOI2017/2018]美術展 题目大意: 有\(n(n\le5\times10^5)\)个物品,每个物品有两个属性:尺寸\(A_i\)和收益\(B_i\).从中选取一个子集,总收益为\(\sum ...

  9. BZOJ2670 : Almost

    求出前缀和$s[]$,那么区间$[l,r]$的几乎平均数$=\frac{s[r]-s[l-1]}{r-l}$. 若只有一个询问,那么可以维护$(i,s[i-1])$的凸壳,在凸壳上二分点$(i,s[i ...

  10. windows安装并使用Anaconda

    前言 本意是要使用Jupyter(Jupyter官网地址),在Jupyter官网上看到,强烈建议新手使用Anaconda,于是开始下载Anaconda使用.Anaconda是用于管理开源包(packa ...