由浅入深,慢慢演化实现框架
两个类的实现代码完全一样,就只有类名或类型不一样的时候,而且还需要不断扩展(未来会增加各种事件)的时候,这时候就用 泛型 + 继承 来提取,继承解决扩展的问题,泛型解决实现代码一致,类不一致的问题,这是一个重构技巧。
表现和数据要分离
数据在大多数情况下需要在多个场景、界面、游戏物体之间是共享的,这些数据不但需要在空间上共享,还需要再时间上也需要共享(需要存储起来),所以在这里,开发者的共识就是把数据的部分会抽离出来,单独放在一个地方进行维护,而比较常见的开发架构就是使用 MVC 的开发架构,我们先不用 MVC 的开发架构,而只用 MVC 中的其中一个概念,就是 Model。
Model 就是管理数据、存储数据,管理数据就是可以通过 Model 对象或类可以对数据进行增删改查,有的时候还可以进行存储。
public class GameModel{public static int KillCount = 0;public static int Gold = 0;public static int Score = 0;public static int BestScore = 0;}
- 用泛型 + 继承 提取 Event 工具类
- 子节点通知父节点也可以用事件(根据情况)
- 表现和需要共享的数据分离
- 正确的代码要放在正确的位置
如果是共享的数据就放在 Model 里,如果不是共享的就不需要。
这里共享的数据可以是配置数据、需要存储的数据、多个地方需要访问的数据。
对于配置数据来说,游戏中的场景和 GameObject、Prefab 在运行游戏之前也是一种配置数据,因为他们本质上是用 Yaml(类似 json、xml 的数据格式)存储在磁盘上的。
而需要存储的数据是从时间这个维度共享的数据,即现在可以访问以前某个时刻存储的数据。
复用 可绑定属性
using System;namespace FrameworkDesign
{public class BindableProperty<T> where T : IEquatable<T>{private T mValue;public T Value{get => mValue;set{if (!mValue.Equals(value)){mValue = value;OnValueChanged?.Invoke(value);}}}public Action<T> OnValueChanged;}
}
BidableProperty 是 数据 + 数据变更事件 的合体,它既存储了数据充当 C# 中的 属性这样的角色,也可以让别的地方监听它的数据变更事件,这样会减少大量的样板代码
- 表现逻辑 适合用 事件 或 委托
- 表现逻辑用方法调用会造成很多问题,Controller 臃肿难维护、
- Model 和 View 是自底向上的关系
- 自底向上用事件或委托
- 自顶向下用方法调用
命令模式
用一个方法来写的逻辑,改成用对象来实现,而这个对象只有一个执行方法。
我们先定义一个接口,叫做 ICommand,代码如下:
namespace FrameworkDesign
{public interface ICommand{void Execute();}
}
实现接口:
public struct AddCountCommand : ICommand{public void Execute(){CounterModel.Count.Value++;}}
Command 模式就是逻辑的调用和执行是分离的
空间分离的方法就是调用的地方和执行的地方放在两个文件里。
时间分离的方法就是调用的之后,Command 过了一点时间才被执行。
而 Command 模式由于有了调用和执行分离这个特点,所以我们可以用不同的数据结构去组织 Command 调用,比如命令队列,再比如用一个命令的堆栈,来实现撤销功能(ctrl + z)