docs: 添加模块系统文档
添加 Extra2D 模块系统的详细文档,包括架构设计、核心接口、创建模块步骤、内置模块说明和最佳实践
This commit is contained in:
parent
8f7f1612eb
commit
269f2d907d
|
|
@ -0,0 +1,505 @@
|
|||
# Extra2D 模块系统
|
||||
|
||||
## 概述
|
||||
|
||||
Extra2D 采用模块化架构设计,所有核心功能都通过模块系统管理。模块系统提供:
|
||||
|
||||
- **统一的生命周期管理**:初始化、关闭、依赖处理
|
||||
- **优先级排序**:确保模块按正确顺序初始化
|
||||
- **配置驱动**:每个模块可独立配置
|
||||
- **解耦设计**:Application 只协调模块,不直接管理任何依赖
|
||||
|
||||
## 架构图
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Application │
|
||||
│ (只负责协调模块,不直接管理任何依赖) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ModuleRegistry │
|
||||
│ (模块注册表,管理所有模块的生命周期) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────────────┼─────────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||
│ Logger Module │ │ Config Module │ │Platform Module│
|
||||
│ (日志系统) │ │ (配置管理) │ │ (平台初始化) │
|
||||
└───────────────┘ └───────────────┘ └───────────────┘
|
||||
│ │ │
|
||||
└─────────────────────┼─────────────────────┘
|
||||
▼
|
||||
┌───────────────┐
|
||||
│ Window Module │
|
||||
│ (窗口管理) │
|
||||
└───────────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────┐
|
||||
│ Render Module │
|
||||
│ (渲染系统) │
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
## 模块优先级
|
||||
|
||||
模块按优先级从小到大初始化,关闭时逆序执行:
|
||||
|
||||
| 优先级值 | 枚举名称 | 用途 | 模块示例 |
|
||||
|---------|---------|------|---------|
|
||||
| 0 | `Core` | 核心模块,最先初始化 | Logger, Config, Platform, Window |
|
||||
| 50 | `Input` | 输入处理 | Input |
|
||||
| 100 | `Graphics` | 图形渲染 | Render |
|
||||
| 200 | `Audio` | 音频系统 | Audio |
|
||||
| 300 | `Physics` | 物理系统 | Physics |
|
||||
| 400 | `Gameplay` | 游戏逻辑 | Gameplay |
|
||||
| 500 | `UI` | 用户界面 | UI |
|
||||
|
||||
## 核心接口
|
||||
|
||||
### IModuleConfig
|
||||
|
||||
模块配置接口,定义模块的元数据和配置:
|
||||
|
||||
```cpp
|
||||
class IModuleConfig {
|
||||
public:
|
||||
virtual ~IModuleConfig() = default;
|
||||
|
||||
// 模块信息
|
||||
virtual ModuleInfo getModuleInfo() const = 0;
|
||||
|
||||
// 配置管理
|
||||
virtual std::string getConfigSectionName() const = 0;
|
||||
virtual bool validate() const = 0;
|
||||
virtual void resetToDefaults() = 0;
|
||||
virtual bool loadFromJson(const void* jsonData) = 0;
|
||||
virtual bool saveToJson(void* jsonData) const = 0;
|
||||
|
||||
// 平台约束
|
||||
virtual void applyPlatformConstraints(PlatformType platform) {}
|
||||
};
|
||||
```
|
||||
|
||||
### IModuleInitializer
|
||||
|
||||
模块初始化器接口,管理模块的生命周期:
|
||||
|
||||
```cpp
|
||||
class IModuleInitializer {
|
||||
public:
|
||||
virtual ~IModuleInitializer() = default;
|
||||
|
||||
// 模块标识
|
||||
virtual ModuleId getModuleId() const = 0;
|
||||
virtual ModulePriority getPriority() const = 0;
|
||||
virtual std::vector<ModuleId> getDependencies() const = 0;
|
||||
|
||||
// 生命周期
|
||||
virtual bool initialize(const IModuleConfig* config) = 0;
|
||||
virtual void shutdown() = 0;
|
||||
virtual bool isInitialized() const = 0;
|
||||
};
|
||||
```
|
||||
|
||||
### ModuleRegistry
|
||||
|
||||
模块注册表,管理所有模块:
|
||||
|
||||
```cpp
|
||||
class ModuleRegistry {
|
||||
public:
|
||||
static ModuleRegistry& instance();
|
||||
|
||||
// 注册模块
|
||||
ModuleId registerModule(
|
||||
UniquePtr<IModuleConfig> config,
|
||||
ModuleInitializerFactory factory
|
||||
);
|
||||
|
||||
// 获取模块
|
||||
IModuleConfig* getModuleConfig(ModuleId id);
|
||||
IModuleInitializer* getInitializer(ModuleId id);
|
||||
|
||||
// 初始化顺序
|
||||
std::vector<ModuleId> getInitializationOrder() const;
|
||||
|
||||
// 查询
|
||||
bool hasModule(const std::string& name) const;
|
||||
std::vector<std::string> getModuleNames() const;
|
||||
};
|
||||
```
|
||||
|
||||
## 创建新模块
|
||||
|
||||
### 步骤 1:定义配置类
|
||||
|
||||
```cpp
|
||||
// my_module.h
|
||||
class MyModuleConfig : public IModuleConfig {
|
||||
public:
|
||||
int someSetting = 42;
|
||||
std::string somePath;
|
||||
|
||||
ModuleInfo getModuleInfo() const override {
|
||||
ModuleInfo info;
|
||||
info.name = "MyModule";
|
||||
info.version = "1.0.0";
|
||||
info.priority = ModulePriority::Gameplay;
|
||||
info.enabled = true;
|
||||
return info;
|
||||
}
|
||||
|
||||
std::string getConfigSectionName() const override {
|
||||
return "my_module";
|
||||
}
|
||||
|
||||
bool validate() const override {
|
||||
return someSetting > 0;
|
||||
}
|
||||
|
||||
void resetToDefaults() override {
|
||||
someSetting = 42;
|
||||
somePath.clear();
|
||||
}
|
||||
|
||||
bool loadFromJson(const void* jsonData) override;
|
||||
bool saveToJson(void* jsonData) const override;
|
||||
};
|
||||
```
|
||||
|
||||
### 步骤 2:定义初始化器
|
||||
|
||||
```cpp
|
||||
// my_module.h
|
||||
class MyModuleInitializer : public IModuleInitializer {
|
||||
public:
|
||||
ModuleId getModuleId() const override { return moduleId_; }
|
||||
ModulePriority getPriority() const override { return ModulePriority::Gameplay; }
|
||||
std::vector<ModuleId> getDependencies() const override { return {}; }
|
||||
|
||||
bool initialize(const IModuleConfig* config) override {
|
||||
if (initialized_) return true;
|
||||
|
||||
const MyModuleConfig* cfg = dynamic_cast<const MyModuleConfig*>(config);
|
||||
if (!cfg) return false;
|
||||
|
||||
// 执行初始化逻辑...
|
||||
|
||||
initialized_ = true;
|
||||
E2D_LOG_INFO("MyModule initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
void shutdown() override {
|
||||
if (!initialized_) return;
|
||||
|
||||
// 执行清理逻辑...
|
||||
|
||||
initialized_ = false;
|
||||
E2D_LOG_INFO("MyModule shutdown");
|
||||
}
|
||||
|
||||
bool isInitialized() const override { return initialized_; }
|
||||
void setModuleId(ModuleId id) { moduleId_ = id; }
|
||||
|
||||
private:
|
||||
ModuleId moduleId_ = INVALID_MODULE_ID;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
```
|
||||
|
||||
### 步骤 3:注册模块
|
||||
|
||||
```cpp
|
||||
// my_module.cpp
|
||||
#include <extra2d/config/module_registry.h>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
static ModuleId s_myModuleId = INVALID_MODULE_ID;
|
||||
|
||||
ModuleId get_my_module_id() {
|
||||
return s_myModuleId;
|
||||
}
|
||||
|
||||
void register_my_module() {
|
||||
if (s_myModuleId != INVALID_MODULE_ID) return;
|
||||
|
||||
s_myModuleId = ModuleRegistry::instance().registerModule(
|
||||
makeUnique<MyModuleConfig>(),
|
||||
[]() -> UniquePtr<IModuleInitializer> {
|
||||
auto initializer = makeUnique<MyModuleInitializer>();
|
||||
initializer->setModuleId(s_myModuleId);
|
||||
return initializer;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// 自动注册
|
||||
namespace {
|
||||
struct MyModuleAutoRegister {
|
||||
MyModuleAutoRegister() {
|
||||
register_my_module();
|
||||
}
|
||||
};
|
||||
|
||||
static MyModuleAutoRegister s_autoRegister;
|
||||
}
|
||||
|
||||
} // namespace extra2d
|
||||
```
|
||||
|
||||
### 步骤 4:在 Application 中使用
|
||||
|
||||
```cpp
|
||||
// application.cpp
|
||||
#include <extra2d/my_module.h>
|
||||
|
||||
bool Application::init(const AppConfig& config) {
|
||||
// 注册模块
|
||||
register_my_module();
|
||||
|
||||
// 初始化所有模块
|
||||
return initModules();
|
||||
}
|
||||
```
|
||||
|
||||
## 内置模块
|
||||
|
||||
### Logger 模块
|
||||
|
||||
**职责**:管理日志系统初始化和关闭
|
||||
|
||||
**配置**:
|
||||
```cpp
|
||||
LoggerModuleConfig config;
|
||||
config.logLevel = LogLevel::Info;
|
||||
config.consoleOutput = true;
|
||||
config.fileOutput = true;
|
||||
config.logFilePath = "app.log";
|
||||
```
|
||||
|
||||
**平台支持**:
|
||||
- Windows:彩色控制台输出
|
||||
- Linux/macOS:ANSI 彩色输出
|
||||
- Switch:libnx console
|
||||
|
||||
---
|
||||
|
||||
### Config 模块
|
||||
|
||||
**职责**:管理 ConfigManager 和应用配置
|
||||
|
||||
**配置**:
|
||||
```cpp
|
||||
ConfigModuleConfig config;
|
||||
config.configPath = "config.json";
|
||||
config.appConfig = AppConfig::createDefault();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Platform 模块
|
||||
|
||||
**职责**:平台检测和平台特定初始化
|
||||
|
||||
**平台特定操作**:
|
||||
- Switch:初始化 romfs 和 socket
|
||||
|
||||
**配置**:
|
||||
```cpp
|
||||
PlatformModuleConfig config;
|
||||
config.targetPlatform = PlatformType::Auto; // 自动检测
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Window 模块
|
||||
|
||||
**职责**:窗口创建和后端管理
|
||||
|
||||
**后端支持**:
|
||||
- SDL2:跨平台
|
||||
- GLFW:跨平台
|
||||
- Switch:原生
|
||||
|
||||
**配置**:
|
||||
```cpp
|
||||
WindowModuleConfig config;
|
||||
config.backend = "sdl2";
|
||||
config.windowConfig.title = "My App";
|
||||
config.windowConfig.width = 1280;
|
||||
config.windowConfig.height = 720;
|
||||
config.windowConfig.vsync = true;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Render 模块
|
||||
|
||||
**职责**:渲染器初始化和管理
|
||||
|
||||
**配置**:
|
||||
```cpp
|
||||
RenderModuleConfig config;
|
||||
config.backend = BackendType::OpenGL;
|
||||
config.vsync = true;
|
||||
config.targetFPS = 60;
|
||||
config.multisamples = 4;
|
||||
```
|
||||
|
||||
## 模块依赖
|
||||
|
||||
模块可以声明依赖关系:
|
||||
|
||||
```cpp
|
||||
std::vector<ModuleId> getDependencies() const override {
|
||||
return { get_window_module_id(), get_config_module_id() };
|
||||
}
|
||||
```
|
||||
|
||||
ModuleRegistry 会自动解析依赖并按正确顺序初始化。
|
||||
|
||||
## 配置文件格式
|
||||
|
||||
模块配置使用 JSON 格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"logger": {
|
||||
"logLevel": 2,
|
||||
"consoleOutput": true,
|
||||
"fileOutput": false
|
||||
},
|
||||
"window": {
|
||||
"backend": "sdl2",
|
||||
"title": "My Application",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"vsync": true
|
||||
},
|
||||
"render": {
|
||||
"backend": "opengl",
|
||||
"targetFPS": 60,
|
||||
"multisamples": 4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 单一职责
|
||||
|
||||
每个模块只负责一个明确的功能领域:
|
||||
|
||||
```
|
||||
✅ Logger Module → 只管理日志
|
||||
✅ Window Module → 只管理窗口
|
||||
❌ Game Module → 管理输入、渲染、音频(职责过多)
|
||||
```
|
||||
|
||||
### 2. 依赖最小化
|
||||
|
||||
模块应尽量减少对其他模块的依赖:
|
||||
|
||||
```cpp
|
||||
// 好的做法:通过接口获取信息
|
||||
std::vector<ModuleId> getDependencies() const override {
|
||||
return { get_window_module_id() }; // 只依赖窗口
|
||||
}
|
||||
|
||||
// 不好的做法:依赖过多
|
||||
std::vector<ModuleId> getDependencies() const override {
|
||||
return {
|
||||
get_window_module_id(),
|
||||
get_config_module_id(),
|
||||
get_logger_module_id(),
|
||||
get_render_module_id()
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 延迟初始化
|
||||
|
||||
资源在需要时才初始化,不是在构造函数中:
|
||||
|
||||
```cpp
|
||||
bool initialize(const IModuleConfig* config) override {
|
||||
if (initialized_) return true;
|
||||
|
||||
// 在这里初始化资源
|
||||
resource_ = createResource();
|
||||
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 安全关闭
|
||||
|
||||
关闭时要检查状态,避免重复关闭:
|
||||
|
||||
```cpp
|
||||
void shutdown() override {
|
||||
if (!initialized_) return; // 避免重复关闭
|
||||
|
||||
// 清理资源
|
||||
resource_.reset();
|
||||
|
||||
initialized_ = false;
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 使用日志
|
||||
|
||||
在关键操作处添加日志:
|
||||
|
||||
```cpp
|
||||
bool initialize(const IModuleConfig* config) override {
|
||||
E2D_LOG_INFO("Initializing MyModule...");
|
||||
|
||||
if (!doSomething()) {
|
||||
E2D_LOG_ERROR("Failed to do something");
|
||||
return false;
|
||||
}
|
||||
|
||||
E2D_LOG_INFO("MyModule initialized successfully");
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
## 调试
|
||||
|
||||
### 查看模块初始化顺序
|
||||
|
||||
```cpp
|
||||
auto order = ModuleRegistry::instance().getInitializationOrder();
|
||||
for (ModuleId id : order) {
|
||||
auto* config = ModuleRegistry::instance().getModuleConfig(id);
|
||||
if (config) {
|
||||
auto info = config->getModuleInfo();
|
||||
E2D_LOG_INFO("Module: {} (priority: {})",
|
||||
info.name, static_cast<int>(info.priority));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 检查模块状态
|
||||
|
||||
```cpp
|
||||
auto* initializer = ModuleRegistry::instance().getInitializer(moduleId);
|
||||
if (initializer && initializer->isInitialized()) {
|
||||
E2D_LOG_INFO("Module is initialized");
|
||||
}
|
||||
```
|
||||
|
||||
## 示例
|
||||
|
||||
完整示例请参考:
|
||||
- [examples/basic/main.cpp](../../examples/basic/main.cpp) - 基础示例
|
||||
- [Extra2D/src/platform/window_module.cpp](../../Extra2D/src/platform/window_module.cpp) - Window 模块实现
|
||||
- [Extra2D/src/graphics/render_module.cpp](../../Extra2D/src/graphics/render_module.cpp) - Render 模块实现
|
||||
Loading…
Reference in New Issue