# Model 包使用说明 ## 概述 Model 包定义了数据模型层的接口和基类。Model 是 MVC 架构中的 M 层,负责管理应用程序的数据和状态。Model 层应该只包含数据和简单的数据逻辑,不包含复杂的业务逻辑。 ## 核心接口 ### [`IModel`](./model.md) 模型接口,定义了模型的基本行为和功能。 **继承的能力接口:** - [`IContextAware`](./rule.md) - 上下文感知接口 - [`ILogAware`](./rule.md) - 日志感知接口 **核心方法:** ```csharp void Init(); // 初始化模型 void OnArchitecturePhase(ArchitecturePhase phase); // 处理架构阶段事件 ``` ### [`ICanGetModel`](./model.md) 标记接口,表示实现者可以获取模型。继承自 [`IBelongToArchitecture`](./rule.md)。 ## 核心类 ### [`AbstractModel`](./model.md) 抽象模型基类,实现IModel接口,提供模型的基础实现。该类继承自[ `ContextAwareBase`](./rule.md),提供了上下文感知能力。 **使用示例:** ```csharp public class PlayerModel : AbstractModel { // 使用 BindableProperty 定义可监听的属性 public BindableProperty Name { get; } = new("Player"); public BindableProperty Level { get; } = new(1); public BindableProperty Health { get; } = new(100); public BindableProperty MaxHealth { get; } = new(100); protected override void OnInit() { // 监听生命值变化 Health.Register(newHealth => { if (newHealth <= 0) { this.SendEvent(new PlayerDiedEvent()); } }); } public override void OnArchitecturePhase(ArchitecturePhase phase) { switch (phase) { case ArchitecturePhase.BeforeModelInit: // 模型初始化前的处理 break; case ArchitecturePhase.AfterModelInit: // 模型初始化后的处理 break; case ArchitecturePhase.Ready: // 架构就绪阶段的处理 break; case ArchitecturePhase.Destroying: // 架构销毁阶段的处理 break; } } } ``` ## Model 的职责 ### ✅ 应该做的事 1. **存储数据和状态** 2. **提供数据访问接口** 3. **监听自身属性变化并做出响应** 4. **发送数据变化事件** 5. **处理架构生命周期事件** ### ❌ 不应该做的事 1. **不包含复杂业务逻辑** - 业务逻辑应该在 System 中 2. **不直接依赖其他 Model** - 通过 Command 协调 3. **不包含 UI 逻辑** - UI 逻辑应该在 Controller 中 ## 常见 Model 示例 ### 玩家数据模型 ```csharp public class PlayerModel : AbstractModel { public BindableProperty PlayerId { get; } = new(""); public BindableProperty PlayerName { get; } = new("Player"); public BindableProperty Level { get; } = new(1); public BindableProperty Health { get; } = new(100); public BindableProperty MaxHealth { get; } = new(100); public BindableProperty Gold { get; } = new(0); public Vector3 Position { get; set; } protected override void OnInit() { Health.Register(hp => { if (hp <= 0) { this.SendEvent(new PlayerDiedEvent()); } }); } public override void OnArchitecturePhase(ArchitecturePhase phase) { switch (phase) { case ArchitecturePhase.Ready: // 模型准备好后的处理 _log?.Log("PlayerModel is ready."); break; default: break; } } } ``` ### 游戏状态模型 ```csharp public class GameModel : AbstractModel { public BindableProperty State { get; } = new(GameState.Menu); public BindableProperty Score { get; } = new(0); public BindableProperty HighScore { get; } = new(0); public BindableProperty CurrentLevel { get; } = new(1); protected override void OnInit() { Score.Register(newScore => { if (newScore > HighScore.Value) { HighScore.Value = newScore; this.SendEvent(new NewHighScoreEvent { Score = newScore }); } }); } public override void OnArchitecturePhase(ArchitecturePhase phase) { switch (phase) { case ArchitecturePhase.Destroying: // 游戏模型清理工作 break; default: break; } } } ``` ## 异步 Model Model 支持异步初始化,通过实现 `IAsyncInitializable` 接口可以在初始化时执行异步操作。 ```csharp // 异步模型示例 public class ConfigModel : AbstractModel, IAsyncInitializable { public BindableProperty Config { get; } = new(null); protected override void OnInit() { // 同步初始化逻辑 } public async Task InitializeAsync() { // 异步加载配置 var storage = this.GetUtility(); var config = await storage.LoadConfigAsync(); Config.Value = config; // 配置加载完成后发送事件 this.SendEvent(new ConfigLoadedEvent { Config = config }); } } // 在架构中使用异步 Model public class GameArchitecture : Architecture { protected override void Init() { RegisterModel(new ConfigModel()); RegisterModel(new PlayerModel()); } } // 异步初始化架构 var architecture = new GameArchitecture(); await architecture.InitializeAsync(); ``` ## 最佳实践 1. **使用 BindableProperty 存储需要监听的数据** 2. **Model 之间不要直接调用,通过 Command/System 协调** 3. **复杂计算和业务逻辑放在 System 中** 4. **使用事件通知数据的重要变化** 5. **保持 Model 简单纯粹,只做数据管理** 6. **对于需要异步加载的数据,实现 IAsyncInitializable 接口** ## 相关包 - [`architecture`](./architecture.md) - 提供 Model 的注册和获取 - [`property`](./property.md) - BindableProperty 用于定义可监听属性 - [`events`](./events.md) - Model 发送事件通知变化 - [`utility`](./utility.md) - Model 可以使用工具类 - [`extensions`](./extensions.md) - 提供 GetModel 等扩展方法