mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 19:03:29 +08:00
- 修复了文档中多个文件的链接指向,统一使用相对路径格式 - 移除了代码块中的语言标识符以保持一致性 - 更新了存储模块文档中的类名显示方式 - 修正了架构文档中的跨文档引用链接 - 调整了事件、命令、查询等核心模块的文档链接结构 - 规范化了所有代码示例的格式和引用方式
11 KiB
11 KiB
Controller 包使用说明
概述
Controller 包定义了控制器(Controller)的接口规范。控制器是 MVC 架构中的 C 层,负责处理用户交互、协调视图和模型,是连接表现层和业务层的桥梁。
注意:本框架使用依赖注入模式,Controller 通过构造函数或属性注入获取架构实例,而非使用全局单例。
核心接口
IController
控制器接口,定义了控制器需要实现的所有功能契约。
继承的能力接口:
ICanSendCommand- 可发送命令ICanGetSystem- 可获取系统ICanGetModel- 可获取模型ICanRegisterEvent- 可注册事件ICanSendQuery- 可发送查询ICanGetUtility- 可获取工具
能力说明:
控制器拥有框架中最全面的能力集合,可以:
- 发送命令执行业务逻辑
- 获取系统调用服务
- 获取模型读写数据
- 注册事件监听变化
- 发送查询获取信息
- 获取工具使用辅助功能
使用示例
基础控制器实现(依赖注入模式)
using GFramework.Core.architecture;
// 通过依赖注入获取架构
public class PlayerController : IController
{
private readonly IArchitecture _architecture;
private readonly IUnRegisterList _unregisterList = new UnRegisterList();
// 通过构造函数注入架构
public PlayerController(IArchitecture architecture)
{
_architecture = architecture;
}
public void Initialize()
{
// 获取模型
var playerModel = _architecture.GetModel<PlayerModel>();
// 监听模型变化
playerModel.Health.RegisterWithInitValue(OnHealthChanged)
.AddToUnregisterList(_unregisterList);
// 注册事件
_architecture.RegisterEvent<PlayerLevelUpEvent>(OnPlayerLevelUp)
.AddToUnregisterList(_unregisterList);
}
// 处理用户输入
public void ProcessInput(double delta)
{
if (Input.IsActionJustPressed("attack"))
{
// 发送命令
_architecture.SendCommand(new AttackCommand());
}
if (Input.IsActionJustPressed("use_item"))
{
// 发送查询
var inventory = _architecture.SendQuery(new GetInventoryQuery());
if (inventory.HasItem("potion"))
{
_architecture.SendCommand(new UseItemCommand("potion"));
}
}
}
private void OnHealthChanged(int newHealth)
{
// 更新 UI 显示
UpdateHealthBar(newHealth);
}
private void OnPlayerLevelUp(PlayerLevelUpEvent e)
{
// 显示升级特效
ShowLevelUpEffect();
}
public void Cleanup()
{
// 清理事件注册
_unregisterList.UnRegisterAll();
}
private void UpdateHealthBar(int health) { /* UI 更新逻辑 */ }
private void ShowLevelUpEffect() { /* 特效逻辑 */ }
}
UI 控制器示例
``csharp // UI 面板控制器 public class MainMenuController : IController { [Inject] private IArchitecture _architecture; [Inject] private IUISystem _uiSystem;
[Export] private Button _startButton;
[Export] private Button _settingsButton;
[Export] private Button _quitButton;
public void Initialize()
{
// 绑定按钮事件
_startButton.Pressed += OnStartButtonPressed;
_settingsButton.Pressed += OnSettingsButtonPressed;
_quitButton.Pressed += OnQuitButtonPressed;
// 获取模型更新 UI
var gameModel = _architecture.GetModel<GameModel>();
UpdateUI(gameModel);
}
private void OnStartButtonPressed()
{
// 通过命令启动游戏
_architecture.SendCommand<StartGameCommand>();
}
private void OnSettingsButtonPressed()
{
// 查询当前设置
var settings = _architecture.SendQuery(new GetSettingsQuery());
// 打开设置面板
_uiSystem.OpenSettingsPanel(settings);
}
private void OnQuitButtonPressed()
{
// 发送退出命令
_architecture.SendCommand<QuitGameCommand>();
}
private void UpdateUI(GameModel model) { /* UI 更新逻辑 */ }
}
### 复杂交互控制器
``csharp
// 战斗控制器
public class CombatController : IController
{
[Inject] protected IArchitecture _architecture;
private IUnRegisterList _unregisterList = new UnRegisterList();
private PlayerModel _playerModel;
private CombatSystem _combatSystem;
[PostConstruct]
public void Init()
{
// 缓存常用引用
_playerModel = _architecture.GetModel<PlayerModel>();
_combatSystem = _architecture.GetSystem<CombatSystem>();
// 注册多个事件
_architecture.RegisterEvent<EnemySpawnedEvent>(OnEnemySpawned)
.AddToUnregisterList(_unregisterList);
_architecture.RegisterEvent<CombatEndedEvent>(OnCombatEnded)
.AddToUnregisterList(_unregisterList);
// 监听模型状态
_playerModel.CombatState.Register(OnCombatStateChanged)
.AddToUnregisterList(_unregisterList);
}
private void OnEnemySpawned(EnemySpawnedEvent e)
{
// 进入战斗状态
_architecture.SendCommand(new EnterCombatCommand(e.Enemy));
}
private void OnCombatEnded(CombatEndedEvent e)
{
if (e.Victory)
{
// 查询奖励
var rewards = _architecture.SendQuery(new CalculateRewardsQuery(e.Enemy));
// 发放奖励
_architecture.SendCommand(new GiveRewardsCommand(rewards));
}
else
{
// 处理失败
_architecture.SendCommand<GameOverCommand>();
}
}
private void OnCombatStateChanged(CombatState state)
{
// 根据战斗状态更新 UI
_architecture.GetSystem<UISystem>().UpdateCombatUI(state);
}
public void Cleanup()
{
_unregisterList.UnRegisterAll();
}
}
控制器职责
✅ 应该做的事
-
处理用户输入
- 键盘、鼠标、触摸输入
- UI 按钮点击
- 手势识别
-
协调视图和模型
- 监听模型变化更新视图
- 将用户操作转换为命令
-
管理界面逻辑
- UI 元素的显示/隐藏
- 动画播放控制
- 视觉反馈
-
事件监听
- 注册关心的事件
- 响应事件更新界面
❌ 不应该做的事
-
不包含业务逻辑
- 业务逻辑应该在 System 中
- 控制器只负责调用和协调
-
不直接修改模型
- 应该通过 Command 修改模型
- 避免直接访问 Model 的 setter
-
不处理复杂计算
- 复杂计算应该在 Query 或 System 中
- 控制器保持简洁
-
不保存核心状态
- 核心状态应该在 Model 中
- 控制器可以保存临时 UI 状态
生命周期管理
事件注销
``csharp public class MyController : IController { [Inject] private IArchitecture _architecture;
// 使用 UnRegisterList 统一管理
private IUnRegisterList _unregisterList = new UnRegisterList();
public void Initialize()
{
// 所有事件注册都添加到列表
_architecture.RegisterEvent<GameEvent>(OnGameEvent)
.AddToUnregisterList(_unregisterList);
_architecture.GetModel<PlayerModel>().Health.Register(OnHealthChanged)
.AddToUnregisterList(_unregisterList);
}
public void Cleanup()
{
// 统一注销所有事件
_unregisterList.UnRegisterAll();
}
}
## 最佳实践
1. **使用依赖注入获取依赖**
- 通过构造函数注入 `IArchitecture`
- 使用 `[Inject]` 属性标记注入字段
2. **保持控制器轻量**
- 复杂逻辑放在 Command、Query、System 中
- 控制器只做协调和转发
3. **合理使用缓存**
- 频繁使用的 Model、System 可以缓存引用
- 平衡性能和内存占用
4. **统一管理事件注销**
- 使用 `IUnRegisterList` 统一管理
- 在 `Cleanup()` 中统一注销
5. **命名规范**
- 控制器类名:`XxxController`
- 使用 `[Inject]` 或构造函数注入获取架构
## 常见模式
### 数据绑定模式
``csharp
public class ScoreController : IController
{
[Inject] private IArchitecture _architecture;
public void Initialize()
{
// 绑定模型数据到 UI
_architecture.GetModel<GameModel>()
.Score
.RegisterWithInitValue(score => UpdateDisplay(score))
.AddToUnregisterList(_unregisterList);
}
private void UpdateDisplay(int score)
{
// 更新分数显示
}
}
状态机模式
``csharp public class PlayerStateController : IController { [Inject] private IArchitecture _architecture; private Dictionary<PlayerState, Action> _stateHandlers;
public void Initialize()
{
_stateHandlers = new Dictionary<PlayerState, Action>
{
{ PlayerState.Idle, HandleIdleState },
{ PlayerState.Moving, HandleMovingState },
{ PlayerState.Attacking, HandleAttackingState }
};
_architecture.GetModel<PlayerModel>()
.State
.Register(OnStateChanged)
.AddToUnregisterList(_unregisterList);
}
private void OnStateChanged(PlayerState state)
{
_stateHandlers[state]?.Invoke();
}
}
## 与 Godot 集成
在 Godot 项目中,可以使用 GFramework.Godot 提供的扩展:
``csharp
using GFramework.Godot;
public partial class GodotPlayerController : Node, IController
{
[Inject] private IArchitecture _architecture;
public override void _Ready()
{
// 使用 Godot 特定的自动注销扩展
_architecture.RegisterEvent<PlayerDiedEvent>(OnPlayerDied)
.UnRegisterWhenNodeExitTree(this);
_architecture.GetModel<PlayerModel>()
.Health
.RegisterWithInitValue(OnHealthChanged)
.UnRegisterWhenNodeExitTree(this);
}
}
相关包
architecture- 提供架构访问能力command- 控制器发送命令执行业务逻辑query- 控制器发送查询获取数据events- 控制器注册事件监听变化model- 控制器读取模型数据system- 控制器调用系统服务extensions- 提供便捷的扩展方法- GFramework.Godot - Godot 特定的控制器扩展
许可证: Apache 2.0