GeWuYou a79f02c987 docs(api): 添加 Core API 参考文档与事件系统接口文档
- 新增 Core API 参考文档,涵盖架构与模块、数据模型与系统、命令与查询等核心组件
- 添加事件系统接口详细文档,包括 IEvent、IEventBus、IUnRegister 等接口说明
- 提供完整的 API 使用示例路径、最佳实践与性能建议
- 包含架构图、依赖关系图与故障排查指南
- 添加测试用例参考与扩展方法说明
- [skip ci]
2026-01-21 23:45:10 +08:00

20 KiB
Raw Blame History

设置模型

**本文引用的文件** - [SettingsModel.cs](file://GFramework.Game/setting/SettingsModel.cs) - [ISettingsModel.cs](file://GFramework.Game.Abstractions/setting/ISettingsModel.cs) - [ISettingsSection.cs](file://GFramework.Game.Abstractions/setting/ISettingsSection.cs) - [ISettingsData.cs](file://GFramework.Game.Abstractions/setting/ISettingsData.cs) - [SettingsSystem.cs](file://GFramework.Game/setting/SettingsSystem.cs) - [ISettingsPersistence.cs](file://GFramework.Game.Abstractions/setting/ISettingsPersistence.cs) - [SettingsPersistence.cs](file://GFramework.Game/setting/SettingsPersistence.cs) - [IApplyAbleSettings.cs](file://GFramework.Game.Abstractions/setting/IApplyAbleSettings.cs) - [SettingsData.cs](file://GFramework.Game.Abstractions/setting/SettingsData.cs) - [AudioSettings.cs](file://GFramework.Game.Abstractions/setting/AudioSettings.cs) - [GraphicsSettings.cs](file://GFramework.Game.Abstractions/setting/GraphicsSettings.cs) - [GodotAudioSettings.cs](file://GFramework.Godot/setting/GodotAudioSettings.cs) - [GodotGraphicsSettings.cs](file://GFramework.Godot/setting/GodotGraphicsSettings.cs) - [SettingsChangedEvent.cs](file://GFramework.Game/setting/events/SettingsChangedEvent.cs) - [SettingsAllLoadedEvent.cs](file://GFramework.Game/setting/events/SettingsAllLoadedEvent.cs)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录API 参考与数据结构示例

简介

本文件面向 GFramework 的“设置模型”子系统,系统性阐述 SettingsModel 类的数据存储机制、ISettingsModel 接口的设计模式、ISettingsSection 的结构化定义、ISettingsData 的数据契约与序列化要求,并给出 API 参考、数据结构示例与典型应用场景。同时,文档覆盖设置数据的一致性保证与并发访问控制建议。

项目结构

设置模型相关代码分布在以下模块:

  • 抽象层Abstractions定义接口契约与通用抽象基类
  • 游戏实现层Game提供具体实现模型、系统、持久化
  • 平台适配层Godot针对 Godot 引擎的具体应用器实现
graph TB
subgraph "抽象层"
A["ISettingsModel.cs"]
B["ISettingsSection.cs"]
C["ISettingsData.cs"]
D["IApplyAbleSettings.cs"]
E["ISettingsPersistence.cs"]
F["SettingsData.cs"]
end
subgraph "游戏实现层"
G["SettingsModel.cs"]
H["SettingsSystem.cs"]
I["SettingsPersistence.cs"]
end
subgraph "平台适配层"
J["GodotAudioSettings.cs"]
K["GodotGraphicsSettings.cs"]
end
A --> G
B --> C
B --> D
C --> F
E --> I
G --> H
H --> D
I --> E
D --> J
D --> K

图表来源

章节来源

核心组件

  • SettingsModel集中管理“数据设置”和“可应用设置”提供注册、检索与聚合查询能力
  • SettingsSystem负责应用设置调用 IApplyAbleSettings.Apply并发布生命周期事件
  • SettingsPersistence负责设置数据的异步加载、保存、存在性检查与批量操作
  • ISettingsData/SettingsData纯数据设置的契约与默认重置行为
  • ISettingsSection/IApplyAbleSettings设置节的结构化定义与可应用设置的执行契约
  • 平台应用器Godot*Settings将设置应用到具体平台如 Godot 音频/图形)

章节来源

架构总览

设置模型采用“模型-系统-持久化”的分层设计,通过接口隔离关注点,确保跨平台可扩展性。

sequenceDiagram
participant Client as "调用方"
participant Model as "SettingsModel"
participant Sys as "SettingsSystem"
participant Persist as "SettingsPersistence"
participant Storage as "IStorage"
Client->>Persist : "LoadAsync<T>()"
Persist->>Storage : "ExistsAsync(key)"
alt 存在
Persist->>Storage : "ReadAsync<T>(key)"
Storage-->>Persist : "T 实例"
Persist-->>Client : "返回已加载设置"
else 不存在
Persist-->>Client : "返回新实例"
end
Client->>Sys : "ApplyAll()"
Sys->>Model : "All()"
Model-->>Sys : "IEnumerable<ISettingsSection>"
loop 遍历每个设置节
Sys->>Sys : "TryApply(section)"
alt section 实现 IApplyAbleSettings
Sys-->>Sys : "Send(SettingsApplyingEvent)"
Sys->>section : "Apply()"
Sys-->>Sys : "Send(SettingsAppliedEvent)"
else
Sys-->>Sys : "忽略"
end
end

图表来源

详细组件分析

SettingsModel设置模型与数据存储机制

  • 数据存储机制
    • 数据设置ISettingsData以类型为键缓存首次访问自动创建并放入字典后续访问直接返回同一实例
    • 可应用设置IApplyAbleSettings显式注册按类型检索用于将设置应用到平台或系统
  • 注册、检索与聚合
    • GetData():自动创建并缓存
    • RegisterApplicator():注册可应用设置,支持链式调用
    • GetApplicator():按类型获取可应用设置(可空)
    • TryGet(Type, out ISettingsSection):优先从数据设置查找,再从可应用设置查找
    • All():合并两类设置节的值,统一暴露给系统进行应用
  • 设计要点
    • 通过两个独立字典隔离“数据持有者”和“应用执行者”,职责清晰
    • 自动创建策略降低调用方心智负担,但需注意生命周期与重置策略
classDiagram
class SettingsModel {
-Dictionary~Type,ISettingsData~ _dataSettings
-Dictionary~Type,IApplyAbleSettings~ _applicators
+GetData~T~() T
+RegisterApplicator~T~(T) ISettingsModel
+GetApplicator~T~() T?
+TryGet(Type, out ISettingsSection) bool
+All() IEnumerable~ISettingsSection~
}
class ISettingsData {
<<interface>>
+Reset() void
}
class IApplyAbleSettings {
<<interface>>
+Apply() Task
}
class ISettingsSection {
<<interface>>
}
SettingsModel ..|> ISettingsModel
ISettingsData --|> ISettingsSection
IApplyAbleSettings --|> ISettingsSection

图表来源

章节来源

ISettingsModel 接口:设计模式与使用场景

  • 方法语义
    • GetData():自动创建并缓存,适合“读多写少”的配置项
    • TryGet(Type, out ISettingsSection):安全检索,避免异常传播
    • GetApplicator():获取应用器,常用于平台适配层
    • All():统一聚合,便于系统一次性应用
    • RegisterApplicator():显式注册,确保应用器可用
  • 使用场景
    • 初始化阶段:通过 GetData() 获取并可能触发 LoadAsync()
    • 应用阶段:通过 All()/TryGet() 遍历并调用 Apply()
    • 维护阶段:通过 Reset() 或重置流程恢复默认值

章节来源

ISettingsSection 与 ISettingsData结构化定义与数据契约

  • ISettingsSection设置节的最小契约用于区分“数据设置”和“可应用设置”
  • ISettingsData继承 ISettingsSection强调“纯数据”特性并提供 Reset() 重置能力
  • SettingsData 抽象基类:提供基于反射的默认 Reset() 实现,按属性类型设置默认值
classDiagram
class ISettingsSection {
<<interface>>
}
class ISettingsData {
<<interface>>
+Reset() void
}
class SettingsData {
+Reset() void
-GetDefaultValue(Type) object?
}
ISettingsData --|> ISettingsSection
SettingsData ..|> ISettingsData

图表来源

章节来源

IApplyAbleSettings 与 SettingsSystem应用与事件

  • IApplyAbleSettings定义 Apply() 异步方法,用于将设置应用到平台或系统
  • SettingsSystem遍历模型中的所有设置节识别可应用设置并调用 Apply(),期间发送“正在应用/已应用”事件
  • 事件模型:通过事件总线广播设置变更与应用结果,便于 UI 或日志系统订阅
sequenceDiagram
participant Sys as "SettingsSystem"
participant Model as "SettingsModel"
participant Sec as "ISettingsSection"
participant App as "IApplyAbleSettings"
Sys->>Model : "All()"
Model-->>Sys : "IEnumerable<ISettingsSection>"
loop 遍历
Sys->>Sec : "TryApply(section)"
alt section 实现 IApplyAbleSettings
Sys-->>Sys : "Send(SettingsApplyingEvent)"
Sys->>App : "Apply()"
Sys-->>Sys : "Send(SettingsAppliedEvent)"
else
Sys-->>Sys : "忽略"
end
end

图表来源

章节来源

SettingsPersistence 与 ISettingsPersistence序列化与一致性

  • 职责边界
    • LoadAsync():若存储存在则反序列化,否则返回新实例;均发送“已加载”事件
    • SaveAsync():序列化并写入存储,发送“已保存”事件
    • ExistsAsync():检查键是否存在
    • DeleteAsync():删除键并发送“已删除”事件
    • SaveAllAsync/LoadAllAsync批量写入与批量加载支持事件聚合
  • 键命名约定Settings_{TypeName}
  • 一致性保证
    • 读取失败时返回新实例,避免崩溃;写入成功后才认为一致
    • 批量操作通过事件聚合(如 SettingsAllLoadedEvent通知上层
  • 并发访问控制建议
    • 对同一类型设置的并发读写应加锁或使用原子更新策略
    • 批量保存/加载建议串行化,避免竞态条件
    • 事件发布与存储写入顺序:先写入存储,再发布事件,确保订阅者看到最新状态
flowchart TD
Start(["开始"]) --> Check["ExistsAsync(key)"]
Check --> |存在| Read["ReadAsync<T>(key)"]
Check --> |不存在| New["new T()"]
Read --> Loaded["发送 SettingsLoadedEvent"]
New --> Loaded
Loaded --> End(["结束"])

图表来源

章节来源

平台应用器示例GodotAudioSettings 与 GodotGraphicsSettings

  • GodotAudioSettings将线性音量转换为分贝并设置到对应音频总线
  • GodotGraphicsSettings根据图形设置调整窗口模式、尺寸与居中
  • 共同特点:实现 IApplyAbleSettings接收对应数据设置作为输入在 Apply() 中执行平台特定逻辑
classDiagram
class AudioSettings {
+float MasterVolume
+float BgmVolume
+float SfxVolume
+Reset() void
}
class GraphicsSettings {
+bool Fullscreen
+int ResolutionWidth
+int ResolutionHeight
+Reset() void
}
class GodotAudioSettings {
+Apply() Task
-SetBus(string,float) void
}
class GodotGraphicsSettings {
+Apply() Task
}
AudioSettings ..|> ISettingsData
GraphicsSettings ..|> ISettingsData
GodotAudioSettings ..|> IApplyAbleSettings
GodotGraphicsSettings ..|> IApplyAbleSettings

图表来源

章节来源

依赖关系分析

  • 松耦合通过接口隔离ISettingsModel、ISettingsData、IApplyAbleSettings、ISettingsPersistence实现跨模块协作
  • 可替换性SettingsPersistence 可替换为其他存储实现(文件、内存、网络),不影响上层逻辑
  • 循环依赖:未见循环依赖;模型与系统通过接口交互,系统与持久化通过接口交互
graph LR
Model["SettingsModel"] --> Abstractions["ISettingsModel/ISettingsData/IApplyAbleSettings"]
System["SettingsSystem"] --> Model
Persistence["SettingsPersistence"] --> Storage["IStorage"]
Persistence --> Abstractions
System --> Abstractions
Platform["Godot*Settings"] --> Abstractions

图表来源

章节来源

性能考量

  • 访问模式
    • GetData() 为 O(1) 查找+首次创建成本,建议在初始化阶段预热常用设置
    • All() 返回合并后的集合,遍历时注意避免重复计算
  • 序列化
    • 大型设置对象建议分块加载或延迟初始化
    • 批量保存/加载时尽量减少事件风暴,必要时合并事件
  • 并发
    • 对同一类型设置的并发读写建议加锁或使用不可变快照
    • Apply() 为异步避免阻塞主线程UI 更新应在主线程回调中进行

故障排查指南

  • 症状:设置未生效
    • 检查是否注册了对应的 IApplyAbleSettings 实现
    • 确认 SettingsSystem.ApplyAll() 已被调用
    • 关注 SettingsAppliedEvent 是否携带异常信息
  • 症状:设置丢失或重置
    • 检查 IStorage 是否正常工作
    • 确认 SettingsPersistence 的键命名规则Settings_{TypeName}
    • 若存在竞态,考虑引入互斥锁或原子更新
  • 症状:事件未触发
    • 确认事件总线已正确初始化
    • 检查 SendEvent 调用路径与异常捕获

章节来源

结论

设置模型通过清晰的接口分层与职责分离,提供了可扩展、可测试且易于维护的设置管理方案。数据设置与可应用设置的双通道设计,既满足了“读多写少”的数据访问需求,又允许平台层以统一契约执行应用逻辑。配合事件总线与持久化抽象,系统可在不同平台与存储介质间灵活切换。

附录API 参考与数据结构示例

API 参考(摘自接口定义)

  • ISettingsModel
    • GetData():获取或创建数据设置
    • TryGet(Type, out ISettingsSection):安全检索设置节
    • GetApplicator():获取可应用设置
    • All():获取全部设置节
    • RegisterApplicator(T):注册可应用设置
  • ISettingsData
    • Reset():重置为默认值
  • IApplyAbleSettings
    • Apply():应用设置到平台
  • ISettingsPersistence
    • LoadAsync()、SaveAsync()、ExistsAsync()、DeleteAsync()
    • SaveAllAsync(IEnumerable)、LoadAllAsync(IEnumerable)

章节来源

数据结构示例(类型与字段)

  • AudioSettings主音量、背景音乐音量、音效音量
  • GraphicsSettings全屏开关、分辨率宽高
  • GodotAudioSettings/GodotGraphicsSettings平台应用器接收对应数据设置并在 Apply() 中执行平台逻辑

章节来源

实际应用场景

  • 游戏启动时:通过 SettingsPersistence.LoadAllAsync 加载已知类型设置,随后 SettingsSystem.ApplyAll 应用到平台
  • 设置面板修改后:调用 SettingsPersistence.SaveAsync 保存,同时触发事件通知 UI 刷新
  • 重置功能:调用 ISettingsData.Reset() 或平台应用器的回滚逻辑