# 领域驱动设计 **本文引用的文件** - [README.md](file://GFramework.Core/README.md) - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs) - [IModel.cs](file://GFramework.Core.Abstractions/model/IModel.cs) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs) - [ISystem.cs](file://GFramework.Core.Abstractions/system/ISystem.cs) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs) - [Architecture.cs](file://GFramework.Core/architecture/Architecture.cs) - [ContextAwareBase.cs](file://GFramework.Core/rule/ContextAwareBase.cs) - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs) - [IState.cs](file://GFramework.Core.Abstractions/state/IState.cs) - [ContextAwareStateBase.cs](file://GFramework.Core/state/ContextAwareStateBase.cs) ## 目录 1. [引言](#引言) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 引言 本教程面向希望在GFramework中实践领域驱动设计(DDD)的游戏开发者。我们将围绕实体(Entity)、值对象(Value Object)、领域事件(Domain Event)、领域服务(Domain Service)等核心概念,结合GFramework现有的架构层、事件系统、命令/查询模式、可绑定属性与状态机等组件,给出可落地的设计与实现思路,并提供游戏开发中的典型应用案例(玩家系统、物品系统、战斗系统)。 ## 项目结构 GFramework采用“约定优于配置”的分层架构,核心分为四层:View/UI、Controller、System、Model、Utility,配合跨层操作(Command/Query/Event)与生命周期管理,形成清晰的职责边界与松耦合通信机制。 ```mermaid graph TB subgraph "表现层" UI["视图/UI"] end subgraph "控制层" CTRL["控制器/Controller"] end subgraph "业务层" SYS["系统/System"] end subgraph "数据层" MDL["模型/Model"] PROP["可绑定属性/Property"] end subgraph "工具层" UT["工具/Utility"] end subgraph "跨层操作" CMD["命令/Command"] QRY["查询/Query"] EVT["事件/Event"] end UI --> CTRL CTRL --> CMD CTRL --> QRY CMD --> SYS QRY --> MDL SYS --> MDL MDL --> EVT SYS --> EVT CTRL --> EVT CTRL --> PROP MDL --> PROP SYS --> UT ``` **图表来源** - [README.md](file://GFramework.Core/README.md#L73-L108) **章节来源** - [README.md](file://GFramework.Core/README.md#L40-L108) ## 核心组件 - 架构与生命周期:通过架构基类集中管理组件注册、初始化阶段与销毁流程,确保组件在正确时机被创建与回收。 - 模型(Model):承载领域状态,提供可绑定属性以实现响应式数据更新。 - 系统(System):处理业务逻辑,通过事件驱动与其他组件解耦。 - 控制器(Controller):桥接UI与业务,监听模型变化并更新界面。 - 命令/查询:封装写操作与读操作,保证操作意图明确且可追踪。 - 事件系统:提供类型化事件总线,支持注册、注销与触发。 - 状态机:管理状态注册、切换与历史,支持状态转换校验与回调。 **章节来源** - [Architecture.cs](file://GFramework.Core/architecture/Architecture.cs#L23-L88) - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) ## 架构总览 下图展示了GFramework中命令执行、事件传播与数据绑定的整体流程,体现DDD中“命令写入状态、事件驱动协作、查询读取状态”的核心思想。 ```mermaid sequenceDiagram participant UI as "用户界面/UI" participant CTRL as "控制器/Controller" participant CMD as "命令/Command" participant SYS as "系统/System" participant MDL as "模型/Model" participant EVT as "事件总线/EventBus" UI->>CTRL : 用户输入 CTRL->>CMD : 构造并发送命令 CMD->>SYS : 执行命令逻辑 SYS->>MDL : 修改领域状态 SYS->>EVT : 发送领域事件 EVT-->>CTRL : 通知控制器 CTRL->>UI : 更新界面显示 ``` **图表来源** - [README.md](file://GFramework.Core/README.md#L102-L108) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L27) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) ## 详细组件分析 ### 实体(Entity) 在GFramework中,实体通常以“模型”形态存在,承载领域不变量与状态。模型通过可绑定属性实现响应式更新,同时通过事件系统对外广播状态变化。 - 关键点 - 模型实现初始化接口,在初始化阶段建立监听与不变量约束。 - 使用可绑定属性作为实体的可变状态载体,避免直接暴露字段。 - 通过事件系统发布领域事件,通知其他组件。 - 代码片段路径 - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [IModel.cs](file://GFramework.Core.Abstractions/model/IModel.cs#L10-L10) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - 设计要点 - 将“状态”与“行为”分离:状态由模型持有,行为由系统处理。 - 不变量通过系统逻辑在命令执行时强制校验,模型仅保存最终状态。 - 事件用于跨组件通知,避免紧耦合。 **章节来源** - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [IModel.cs](file://GFramework.Core.Abstractions/model/IModel.cs#L7-L10) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) ### 值对象(Value Object) 值对象强调“不可变性”与“相等性基于结构”。在GFramework中,可通过可绑定属性的比较器定制与事件系统实现值对象语义。 - 关键点 - 使用可绑定属性的比较器定制,确保相等判断符合值对象语义。 - 值对象作为命令输入或查询条件,提升意图表达力。 - 通过事件系统传播值对象的变化,便于系统与模型响应。 - 代码片段路径 - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L103-L107) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L27) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - 设计要点 - 值对象不应暴露可变状态;若需变化,应通过新实例替换。 - 在命令/查询中以值对象作为输入参数,增强可读性与可测试性。 **章节来源** - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L103-L107) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L27) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) ### 领域事件(Domain Event) 领域事件是跨组件通信的关键手段,GFramework提供类型化事件总线与简单事件类,支持注册、注销与触发。 - 关键点 - 事件类型化,确保强类型安全与可发现性。 - 事件总线支持注册/注销与触发,便于系统与模型响应。 - 简单事件类提供无参事件的注册/触发能力,适配部分场景。 - 代码片段路径 - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L8-L39) - 设计要点 - 领域事件应描述“发生了什么”,而非“如何处理”。 - 事件发布应发生在状态变更之后,确保订阅者看到一致状态。 **章节来源** - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L8-L39) ### 领域服务(Domain Service) 领域服务封装跨实体的业务逻辑与规则。在GFramework中,系统层承担领域服务职责,通过事件驱动与其他组件协作。 - 关键点 - 系统实现业务规则,监听事件并修改模型状态。 - 通过架构基类提供的上下文能力访问容器与服务。 - 生命周期管理确保系统在正确阶段初始化与销毁。 - 代码片段路径 - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [ISystem.cs](file://GFramework.Core.Abstractions/system/ISystem.cs#L7-L11) - [Architecture.cs](file://GFramework.Core/architecture/Architecture.cs#L23-L88) - 设计要点 - 领域服务不持有状态,仅处理业务规则与流程编排。 - 通过事件与模型解耦,避免循环依赖。 **章节来源** - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [ISystem.cs](file://GFramework.Core.Abstractions/system/ISystem.cs#L7-L11) - [Architecture.cs](file://GFramework.Core/architecture/Architecture.cs#L23-L88) ### 状态机(状态驱动的领域) 状态机用于管理复杂的状态流转与转换规则,适合角色状态、UI状态等场景。 - 关键点 - 状态注册、切换、历史记录与回退。 - 转换前的合法性校验与拒绝回调。 - 状态进入/退出与状态变更回调。 - 代码片段路径 - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) - [IState.cs](file://GFramework.Core.Abstractions/state/IState.cs#L6-L26) - [ContextAwareStateBase.cs](file://GFramework.Core/state/ContextAwareStateBase.cs#L13-L74) - 设计要点 - 状态转换规则集中在状态机内,避免分散的条件判断。 - 历史记录支持回退,便于撤销与审计。 **章节来源** - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) - [IState.cs](file://GFramework.Core.Abstractions/state/IState.cs#L6-L26) - [ContextAwareStateBase.cs](file://GFramework.Core/state/ContextAwareStateBase.cs#L13-L74) ### 命令与查询(CQRS) 命令/查询职责分离,命令封装写操作,查询封装读操作,二者均通过上下文感知基类接入架构。 - 关键点 - 命令:带输入参数,执行后可能修改模型状态并发布事件。 - 查询:只读操作,返回结果给调用方。 - 上下文感知:命令/查询可访问架构上下文与容器。 - 代码片段路径 - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - [ContextAwareBase.cs](file://GFramework.Core/rule/ContextAwareBase.cs#L10-L43) - 设计要点 - 命令应具备可撤销/可重试能力(可结合持久化与日志)。 - 查询应避免副作用,确保幂等性。 **章节来源** - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - [ContextAwareBase.cs](file://GFramework.Core/rule/ContextAwareBase.cs#L10-L43) ## 依赖关系分析 下图展示DDD相关组件在GFramework中的依赖关系与交互: ```mermaid classDiagram class Architecture { +Initialize() +RegisterModel() +RegisterSystem() +RegisterUtility() +Destroy() } class ContextAwareBase { +SetContext(context) +GetContext() +OnContextReady() } class AbstractModel { +OnInit() +OnArchitecturePhase(phase) } class AbstractSystem { +Init() +Destroy() +OnInit() +OnDestroy() } class BindableProperty~T~ { +Value +Register() +RegisterWithInitValue() +UnRegister() } class AbstractCommand~TInput,TResult~ { +Execute() +OnExecute(input) } class AbstractQuery~TInput,TResult~ { +Do() +OnDo(input) } class EventBus { +Register() +UnRegister() +Send() } class StateMachine { +Register() +Unregister() +ChangeTo() +GoBack() +GetStateHistory() } class IState { +OnEnter(from) +OnExit(to) +CanTransitionTo(target) } Architecture --> AbstractModel : "注册/初始化" Architecture --> AbstractSystem : "注册/初始化" ContextAwareBase <|-- AbstractModel ContextAwareBase <|-- AbstractSystem ContextAwareBase <|-- AbstractCommand ContextAwareBase <|-- AbstractQuery AbstractSystem --> EventBus : "发布事件" AbstractModel --> BindableProperty : "持有状态" AbstractCommand --> AbstractModel : "修改状态" AbstractQuery --> AbstractModel : "读取状态" StateMachine --> IState : "管理状态" ``` **图表来源** - [Architecture.cs](file://GFramework.Core/architecture/Architecture.cs#L23-L88) - [ContextAwareBase.cs](file://GFramework.Core/rule/ContextAwareBase.cs#L10-L43) - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) - [IState.cs](file://GFramework.Core.Abstractions/state/IState.cs#L6-L26) **章节来源** - [Architecture.cs](file://GFramework.Core/architecture/Architecture.cs#L23-L88) - [ContextAwareBase.cs](file://GFramework.Core/rule/ContextAwareBase.cs#L10-L43) - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) - [IState.cs](file://GFramework.Core.Abstractions/state/IState.cs#L6-L26) ## 性能考量 - 事件风暴与订阅管理 - 使用统一的注销列表管理事件订阅,避免重复注册与内存泄漏。 - 事件总线按类型索引事件,减少遍历成本。 - 可绑定属性 - 通过比较器避免无效回调;批量更新时可使用“无事件设置”降低触发频率。 - 状态机历史 - 历史记录大小受控,避免无限增长导致内存压力。 - 生命周期 - 架构阶段化初始化与冻结容器,减少运行期开销。 [本节为通用指导,无需列出章节来源] ## 故障排查指南 - 事件未触发/未收到 - 检查事件类型是否匹配,确认注册与注销是否成对出现。 - 确认事件总线是否在正确阶段可用。 - 状态无法切换 - 检查状态转换规则与目标状态是否已注册。 - 查看拒绝回调与历史记录是否影响回退。 - 命令执行后状态未更新 - 确认命令是否正确修改模型状态并发布事件。 - 检查系统是否监听到相应事件并处理。 - UI 不更新 - 确认模型属性使用可绑定属性并在控制器中注册回调。 - 检查控制器是否在初始化阶段完成注册。 **章节来源** - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L8-L39) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) ## 结论 通过将DDD的核心概念映射到GFramework的分层架构与现有组件(模型、系统、事件、命令/查询、状态机、可绑定属性),可以构建高内聚、低耦合、可测试且可演进的游戏领域模型。建议在实际项目中: - 将“状态”放入模型,“行为”放入系统; - 使用命令/查询明确写读意图; - 用事件解耦跨组件协作; - 用值对象表达不可变语义; - 用状态机管理复杂状态流转。 [本节为总结,无需列出章节来源] ## 附录 ### 游戏开发中的DDD应用案例 - 玩家系统(Player) - 实体:玩家模型持有生命值、金币等可绑定属性。 - 领域事件:玩家死亡、升级、获得物品等事件。 - 领域服务:经验计算、等级上限校验、掉落分配。 - 代码片段路径 - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - 物品系统(Item) - 值对象:物品属性(品质、数量、叠加上限)。 - 命令:拾取、丢弃、合成、装备/卸下。 - 查询:背包容量、某类物品数量、可合成配方。 - 代码片段路径 - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - 战斗系统(Combat) - 领域事件:造成伤害、承受伤害、击杀、闪避。 - 领域服务:伤害计算、护甲减免、暴击判定、状态效果。 - 状态机:待机、移动、攻击、受击、死亡、眩晕。 - 代码片段路径 - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) - [IState.cs](file://GFramework.Core.Abstractions/state/IState.cs#L6-L26) ### DDD概念与GFramework组件映射表 - 实体(Entity) ↔ 模型(Model) + 可绑定属性(BindableProperty) - 值对象(Value Object) ↔ 命令/查询输入 + 比较器定制 - 领域事件(Domain Event) ↔ 事件总线(EventBus) + 简单事件(EasyEvent) - 领域服务(Domain Service) ↔ 系统(System) - 命令/查询(CQRS) ↔ 命令(AbstractCommand) + 查询(AbstractQuery) - 状态机(State Machine) ↔ 状态机(StateMachine) **章节来源** - [AbstractModel.cs](file://GFramework.Core/model/AbstractModel.cs#L11-L33) - [BindableProperty.cs](file://GFramework.Core/property/BindableProperty.cs#L11-L135) - [AbstractCommand.cs](file://GFramework.Core/command/AbstractCommand.cs#L11-L52) - [AbstractQuery.cs](file://GFramework.Core/query/AbstractQuery.cs#L11-L28) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L8-L54) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L8-L39) - [AbstractSystem.cs](file://GFramework.Core/system/AbstractSystem.cs#L13-L61) - [StateMachine.cs](file://GFramework.Core/state/StateMachine.cs#L8-L276) - [IState.cs](file://GFramework.Core.Abstractions/state/IState.cs#L6-L26)