允许一个单一的实体跨越多个不同域而不会导致耦合。
(摘自《游戏编程模式》)
组件模式又是一个采用“Have One”实现多态的模式。从客观上来说,Unity引擎的GameObject就是使用组件尤为成功的例子。在使用Unity开发中,我们可以给一个GameObject添加引擎自带或自己编写的组件。下图展示了某个项目中一个VR人物游戏对象上面绑定的组件,我们将从这个案例中引入我们即将介绍的组件模式。
根据图片,VR角色模型绑定了Transform、Animator、VRIK、CalibrateSize、CharacterWalkLomotion、WalkingJitter以及BonesTransformData七个根组件。从命名上我们不难猜测他们的作用:
- Transform:管理这个角色的位置
- Animator:管理角色的动画
- VRIK:VR的反向动力学
- CalibrateSize:角色身材大小管理
- CharacterWalkLomotion:角色行走相关
- WalkingJitter:模拟行走抖动
- BonesTransformData:角色骨骼数据(位置、旋转方向等)
仔细探讨它们的组织形式,我们都知道,重用功能主要的实现方式就是继承和Have One。首先我们先来探讨用继承的方式实现,其代码结构如下图所示:
我们来仔细分析以下整个角色模块。其实通过继承来共享功能在这个例子中是一件很得不偿失得的方案。理由如下:
- 在各个继承关系中,子类仅仅是需要某一些数据、某一些函数。而不是所有数据。
- 子类不希望是父类的类似实例。Animator不希望成为和Transform家族(他们根本没有太多类似的地方),然而继承把它们绑在了一起,并强行让Animator认爹。
- 类与类之间的逻辑已经变得太过复杂。上面的结构图还不是功能完整的结构图。
Unity不可能傻到这样设计。因此,组件模式就发挥了巨大的作用。运用组件模式,我们可以将代码按照以下结构图进行组织:
角色拥有了这些类的一个实例。实例之间还可以通过角色互相访问和调用,并且这些类也没有相互耦合。这就是组件模式。每一个类都表示一个组件。