This commit is contained in:
coco
2026-07-03 16:05:30 +08:00
commit df489d5640
1101 changed files with 779140 additions and 0 deletions
@@ -0,0 +1,313 @@
# 单例模式
<cite>
**本文引用的文件**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
- [GeoMative.h](file://h/GeoMative.h)
- [Global.cpp](file://cpp/Main/Global.cpp)
- [DevManager.h](file://h/DevManager.h)
- [ProManager.h](file://h/ProManager.h)
- [TdManager.h](file://h/TdManager.h)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
## 引言
本文件聚焦于CGeoMativeApp类在MFC框架下的单例模式实现与应用。CGeoMativeApp继承自CWinApp,作为全局应用程序对象,负责应用生命周期管理(InitInstance/ExitInstance)、全局资源初始化与释放、以及通过成员指针(如m_pDevManager、m_pProManager等)向全应用提供统一的核心管理器访问入口。本文将从代码结构、控制流、资源管理一致性与全局状态统一性等方面,系统解析该单例模式的设计与实践,并给出典型应用场景与潜在风险提示。
## 项目结构
- 应用程序入口与主框架位于Main目录,包含CGeoMativeApp类及其声明。
- 全局单例实例theApp在Global.cpp中定义,确保全局唯一性。
- 核心管理器(设备、项目、测试数据等)在各自的头文件中声明,CGeoMativeApp在InitInstance中创建并持有它们的指针,形成全局可访问的资源中心。
```mermaid
graph TB
subgraph "主程序层"
A["CGeoMativeApp<br/>全局应用对象"]
B["MainFrm<br/>主MDI框架"]
end
subgraph "管理器层"
C["CDevManager<br/>设备管理"]
D["CProManager<br/>项目管理"]
E["CTdManager<br/>测试数据管理"]
F["CExecManager<br/>执行管理"]
G["CSptManager<br/>脚本管理"]
H["CIOManager<br/>IO管理"]
end
subgraph "外部资源"
I["数据库连接<br/>_ConnectionPtr"]
J["网络操作<br/>CNetWorkOper"]
end
A --> B
A --> C
A --> D
A --> E
A --> F
A --> G
A --> H
A --> I
A --> J
```
图表来源
- [GeoMative.h](file://h/GeoMative.h#L114-L181)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L139-L642)
章节来源
- [GeoMative.h](file://h/GeoMative.h#L114-L181)
- [Global.cpp](file://cpp/Main/Global.cpp#L23-L26)
## 核心组件
- CGeoMativeApp:从CWinApp派生,重写InitInstance/ExitInstance,承担应用启动与退出阶段的初始化与清理工作;同时维护全局管理器指针,提供跨模块访问。
- theApp:全局唯一实例,由Global.cpp定义,保证单例语义。
- 管理器集合:设备管理、项目管理、测试数据管理、执行管理、脚本管理、IO管理等,均由CGeoMativeApp在InitInstance中创建并持有。
章节来源
- [GeoMative.h](file://h/GeoMative.h#L114-L181)
- [Global.cpp](file://cpp/Main/Global.cpp#L23-L26)
## 架构总览
CGeoMativeApp作为全局应用对象,贯穿应用生命周期:
- 启动阶段:InitInstance负责初始化MFC、主窗口、数据库连接、网络、线程、配置读取、管理器创建等。
- 运行阶段:各模块通过CGeoMativeApp提供的全局指针访问核心资源。
- 退出阶段:ExitInstance负责反向销毁顺序、关闭数据库连接、释放资源、清理线程与临界区。
```mermaid
sequenceDiagram
participant App as "CGeoMativeApp"
participant Win as "CWinApp基类"
participant UI as "主窗口(MainFrm)"
participant DB as "数据库连接"
participant Net as "网络操作"
participant Mgr as "管理器集合"
App->>Win : 调用基类构造
App->>App : 构造函数初始化成员指针为空
App->>Win : InitInstance()
Win-->>App : 返回TRUE/FALSE
App->>UI : 创建并显示主窗口
App->>DB : 建立数据库连接
App->>Mgr : 创建管理器实例并赋值给m_p*指针
App->>Net : 初始化网络与线程
App-->>UI : 设置状态栏/菜单/语言
App->>Win : 进入消息循环
App->>Win : ExitInstance()
Win-->>App : 返回退出码
App->>Mgr : 逐个delete管理器
App->>DB : 关闭连接并释放
App->>Net : 清理网络与线程
App->>UI : 删除主窗口
```
图表来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L139-L642)
- [GeoMative.h](file://h/GeoMative.h#L114-L181)
## 详细组件分析
### CGeoMativeApp单例实现与生命周期
- 单例语义:theApp在Global.cpp中定义为全局变量,确保应用范围内仅存在一个CGeoMativeApp实例,从而天然满足单例要求。
- 生命周期管理:
- 构造函数:初始化成员指针为空,设置默认运行参数。
- InitInstance:完成MFC初始化、主窗口创建、数据库连接、网络初始化、线程创建、配置读取、管理器创建等。
- ExitInstance:逆序释放管理器、关闭数据库连接、释放网络资源、销毁主窗口、清理线程与临界区。
```mermaid
classDiagram
class CWinApp
class CGeoMativeApp {
+CGeoMativeApp()
+~CGeoMativeApp()
+InitInstance() bool
+ExitInstance() int
+PreTranslateMessage(pMsg) bool
+OnFileExit() void
+OnHelpAbout() void
+m_pDevManager : CDevManager*
+m_pProManager : CProManager*
+m_pTdManager : CTdManager*
+m_pExecManager : CExecManager*
+m_pSptManager : CSptManager*
+m_pIOManager : CIOManager*
+m_pConnection : _ConnectionPtr
+m_NetWorkOper : CNetWorkOper
}
CGeoMativeApp --|> CWinApp
```
图表来源
- [GeoMative.h](file://h/GeoMative.h#L114-L181)
章节来源
- [Global.cpp](file://cpp/Main/Global.cpp#L23-L26)
- [GeoMative.h](file://h/GeoMative.h#L114-L181)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L56-L129)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L139-L642)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L644-L820)
### 启动流程与资源初始化(InitInstance
- MFC与OLE初始化:启用MFC、OLE、控件容器等。
- 主窗口创建:加载并显示MDI主框架。
- 数据库连接:创建ADO连接,打开数据库文件,设置锁策略。
- 网络与线程:初始化网络操作、启动系统时间线程、扫描线程等。
- 配置读取:从配置文件读取传输方式、用户信息、语言、时区等。
- 管理器创建:按顺序创建设备、项目、测试数据、执行、脚本、IO等管理器实例,并保存到m_p*指针,供后续模块使用。
- 登录与网络:根据传输方式决定在线/离线登录流程,启动心跳包或广播等。
- 状态与日志:初始化日志、清理旧日志、设置状态栏文本。
```mermaid
flowchart TD
Start(["进入InitInstance"]) --> OLE["初始化MFC/OLE/控件容器"]
OLE --> Win["创建并显示主窗口"]
Win --> DB["建立数据库连接"]
DB --> Net["初始化网络与线程"]
Net --> Cfg["读取配置信息"]
Cfg --> Mgrs["创建管理器实例并赋值到m_p*"]
Mgrs --> Login["在线/离线登录处理"]
Login --> Threads["启动定时器/心跳/扫描线程"]
Threads --> Ready(["应用就绪"])
```
图表来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L139-L642)
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L139-L642)
### 退出流程与资源回收(ExitInstance
- 逆序释放:先释放主窗口,再逐个delete管理器,最后关闭数据库连接。
- 网络与线程:停止网络操作、等待扫描线程安全退出、释放线程句柄。
- COM与临界区:关闭COM、删除扫描临界区。
- 错误处理:捕获异常并调用基类ExitInstance,保证退出路径稳定。
```mermaid
flowchart TD
ExitStart(["进入ExitInstance"]) --> CloseWin["删除主窗口"]
CloseWin --> DelMgrs["逐个delete管理器"]
DelMgrs --> CloseDB["关闭数据库连接并释放"]
CloseDB --> NetClean["停止网络操作/线程清理"]
NetClean --> COM["CoUninitialize/删除临界区"]
COM --> BaseExit["调用基类ExitInstance"]
BaseExit --> ExitEnd(["退出完成"])
```
图表来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L644-L737)
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L644-L737)
### 全局管理器的创建与使用
- 设备管理器:负责设备发现、注册、远程设备管理等。
- 项目管理器:负责工程、测区、DMS树等结构的创建与同步。
- 测试数据管理器:负责各类测试数据的导入、上传、转换等。
- 执行、脚本、IO管理器:分别负责任务执行、脚本管理、IO交互等。
```mermaid
classDiagram
class CGeoMativeApp {
+m_pDevManager : CDevManager*
+m_pProManager : CProManager*
+m_pTdManager : CTdManager*
+m_pExecManager : CExecManager*
+m_pSptManager : CSptManager*
+m_pIOManager : CIOManager*
}
class CDevManager
class CProManager
class CTdManager
class CExecManager
class CSptManager
class CIOManager
CGeoMativeApp --> CDevManager : "创建并持有"
CGeoMativeApp --> CProManager : "创建并持有"
CGeoMativeApp --> CTdManager : "创建并持有"
CGeoMativeApp --> CExecManager : "创建并持有"
CGeoMativeApp --> CSptManager : "创建并持有"
CGeoMativeApp --> CIOManager : "创建并持有"
```
图表来源
- [GeoMative.h](file://h/GeoMative.h#L144-L169)
- [DevManager.h](file://h/DevManager.h#L16-L66)
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [TdManager.h](file://h/TdManager.h#L30-L106)
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L424-L431)
- [DevManager.h](file://h/DevManager.h#L16-L66)
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [TdManager.h](file://h/TdManager.h#L30-L106)
### 单例模式在MFC中的典型应用场景
- 全局状态集中管理:通过CGeoMativeApp集中管理数据库连接、网络、线程、配置等,避免分散在各模块导致状态漂移。
- 资源生命周期统一:InitInstance集中初始化,ExitInstance集中释放,确保资源分配与回收成对出现,降低泄漏风险。
- 模块间解耦:各模块通过m_p*指针访问核心资源,无需自行创建或管理,降低耦合度。
- 全局事件与消息:通过OnFileExit/OnHelpAbout等消息处理,统一响应用户操作。
章节来源
- [GeoMative.h](file://h/GeoMative.h#L170-L181)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L792-L820)
### 单例模式的潜在风险与建议
- 线程安全:CGeoMativeApp作为全局单例,若多线程并发访问其成员(尤其是共享资源如数据库连接、网络句柄),需考虑加锁或使用线程安全接口。
- 资源竞争:多个管理器共享同一数据库连接,应避免在同一事务中长时间占用连接,防止阻塞。
- 依赖膨胀:全局对象可能成为“上帝对象”,建议通过接口抽象与依赖注入逐步拆分职责。
- 测试困难:全局状态使单元测试难以隔离,建议在测试环境中提供可替换的全局对象或工厂。
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L139-L642)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L644-L737)
## 依赖关系分析
- CGeoMativeApp依赖于多个管理器类(设备、项目、测试数据、执行、脚本、IO),并在InitInstance中创建实例。
- CGeoMativeApp还依赖数据库连接与网络操作,用于数据持久化与远程通信。
- 全局单例theApp确保CGeoMativeApp在整个进程内唯一,避免重复初始化与资源冲突。
```mermaid
graph LR
App["CGeoMativeApp"] --> DevMgr["CDevManager"]
App --> ProMgr["CProManager"]
App --> TdMgr["CTdManager"]
App --> ExecMgr["CExecManager"]
App --> SptMgr["CSptManager"]
App --> IoMgr["CIOManager"]
App --> Conn["_ConnectionPtr"]
App --> Net["CNetWorkOper"]
```
图表来源
- [GeoMative.h](file://h/GeoMative.h#L144-L169)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L424-L431)
章节来源
- [GeoMative.h](file://h/GeoMative.h#L114-L181)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L139-L642)
## 性能考量
- 启动阶段的I/O与网络初始化会阻塞主线程,建议在后台线程中进行非关键初始化,或采用延迟初始化策略。
- 数据库连接与事务:批量操作时合并事务,减少提交次数;避免长事务占用连接。
- 线程与临界区:扫描线程与系统时间线程需合理调度,避免CPU占用过高;临界区保护共享数据结构。
- 日志与磁盘:日志写入应缓冲并异步化,避免频繁磁盘I/O影响UI响应。
## 故障排查指南
- 数据库连接失败:检查数据库路径、权限与密码;确认InitInstance中连接逻辑与异常分支。
- 网络初始化失败:检查IP/端口配置、网络连通性与线程启动结果。
- 管理器创建异常:关注异常捕获与回滚逻辑,定位具体管理器初始化问题。
- 退出异常:ExitInstance中捕获异常并调用基类ExitInstance,确保进程稳定退出。
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L232-L310)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L503-L521)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L644-L737)
## 结论
CGeoMativeApp通过theApp全局单例与CWinApp生命周期钩子,实现了应用级资源的集中管理与统一释放。InitInstance/ExitInstance的职责划分清晰,配合管理器集合的创建与持有,为全应用提供了稳定的全局访问入口。实践中应注意线程安全、资源竞争与依赖膨胀等问题,以确保系统的健壮性与可维护性。
@@ -0,0 +1,384 @@
# 工厂模式
<cite>
**本文引用的文件**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [ProManager.h](file://h/ProManager.h)
- [HandleProcessor.h](file://h/HandleProcessor.h)
- [LinkList.h](file://h/LinkList.h)
- [DataMngStruct.h](file://h/DataMngStruct.h)
- [Project.h](file://h/Project.h)
- [TestingZone.h](file://h/TestingZone.h)
- [Constant.h](file://h/Constant.h)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 引言
本文件围绕 CProManager::GetDMS() 方法展开,系统性解析其作为“工厂模式”的具体实现:如何依据传入的句柄(DWORD dwHandle)在内部链表 m_dmsLinkList 中查找并返回相应的 CDataMngStruct 派生对象;如何通过类型识别逻辑(句柄风格)动态创建对象;以及对象生命周期控制与缓存复用策略。同时结合实际调用场景,说明该工厂模式如何实现管理对象的动态创建与解耦,提升系统的可扩展性与可维护性,并给出在“项目管理”与“测区管理”中的具体应用路径。
## 项目结构
与工厂模式直接相关的核心模块与文件如下:
- 管理器层:CProManager 负责数据管理对象的工厂与缓存
- 句柄处理器:CHandleProcessor 提供句柄解析与生成能力
- 链表容器:CLinkList 模板类提供按句柄索引的对象缓存
- 抽象基类:CDataMngStruct 定义统一接口
- 具体派生类:CProject、CTestingZone 分别代表“项目”和“测区”
- 常量定义:PZ_STYLE_* 标识不同对象类型
- 使用方:CDataOperator 在视图交互中调用 GetDMS 获取对象并展示详情
```mermaid
graph TB
subgraph "管理器层"
PM["CProManager<br/>工厂与缓存"]
end
subgraph "句柄处理"
HP["CHandleProcessor<br/>解析/生成句柄"]
end
subgraph "容器"
LL["CLinkList&lt;CDataMngStruct*&gt;<br/>按句柄缓存"]
end
subgraph "抽象与派生"
DMS["CDataMngStruct<br/>抽象接口"]
PRJ["CProject<br/>项目"]
TZ["CTestingZone<br/>测区"]
end
subgraph "常量"
CST["Constant.h<br/>PZ_STYLE_*"]
end
subgraph "使用方"
DO["CDataOperator<br/>调用GetDMS"]
end
PM --> HP
PM --> LL
PM --> DMS
DMS --> PRJ
DMS --> TZ
PM --> CST
DO --> PM
```
图表来源
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [HandleProcessor.h](file://h/HandleProcessor.h#L12-L24)
- [LinkList.h](file://h/LinkList.h#L14-L43)
- [DataMngStruct.h](file://h/DataMngStruct.h#L14-L20)
- [Project.h](file://h/Project.h#L14-L21)
- [TestingZone.h](file://h/TestingZone.h#L12-L19)
- [Constant.h](file://h/Constant.h#L80-L110)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L488-L499)
章节来源
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
- [HandleProcessor.h](file://h/HandleProcessor.h#L12-L24)
- [LinkList.h](file://h/LinkList.h#L14-L43)
- [DataMngStruct.h](file://h/DataMngStruct.h#L14-L20)
- [Project.h](file://h/Project.h#L14-L21)
- [TestingZone.h](file://h/TestingZone.h#L12-L19)
- [Constant.h](file://h/Constant.h#L80-L110)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L488-L499)
## 核心组件
- CProManager::GetDMS:工厂入口,负责根据句柄风格创建或复用对象,并通过链表缓存返回
- CHandleProcessor:从句柄中提取类型(style)与标识(ID),并支持生成新句柄
- CLinkList:模板链表,以句柄为键存储对象指针,提供查找、添加、删除等操作
- CDataMngStruct:抽象基类,定义统一的展示接口
- CProject、CTestingZone:具体派生类,分别对应“项目”和“测区”,构造时携带数据库连接与ID
- PZ_STYLE_*:类型枚举,用于区分不同管理对象类型
章节来源
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [HandleProcessor.h](file://h/HandleProcessor.h#L12-L24)
- [LinkList.h](file://h/LinkList.h#L14-L43)
- [DataMngStruct.h](file://h/DataMngStruct.h#L14-L20)
- [Project.h](file://h/Project.h#L14-L21)
- [TestingZone.h](file://h/TestingZone.h#L12-L19)
- [Constant.h](file://h/Constant.h#L80-L110)
## 架构总览
CProManager::GetDMS 的工作流如下:
- 从句柄中解析类型(style)与ID
- 在 m_dmsLinkList 中按句柄查找对象
- 若未命中,则根据 style 创建相应派生类对象(如 CProject 或 CTestingZone
- 将新对象加入缓存链表后返回
- 调用方通过返回的 CDataMngStruct* 调用统一接口(如 ShowDetailInfo
```mermaid
sequenceDiagram
participant Caller as "调用方"
participant PM as "CProManager"
participant HP as "CHandleProcessor"
participant LL as "CLinkList"
participant PRJ as "CProject"
participant TZ as "CTestingZone"
Caller->>PM : GetDMS(dwHandle)
PM->>HP : GetStyleFromHandle(dwHandle)
PM->>LL : Get(dwHandle)
alt 未命中缓存
PM->>HP : GetIDFromHandle(dwHandle)
PM->>PM : switch(style)
opt style==PZ_STYLE_PRO
PM->>PRJ : new CProject(ID, Connection)
end
opt style==PZ_STYLE_TZ
PM->>TZ : new CTestingZone(ID, Connection)
end
PM->>LL : Add(dwHandle, pDMS)
end
PM-->>Caller : 返回 pDMS
```
图表来源
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
- [HandleProcessor.h](file://h/HandleProcessor.h#L17-L21)
- [LinkList.h](file://h/LinkList.h#L28-L31)
- [Project.h](file://h/Project.h#L18-L21)
- [TestingZone.h](file://h/TestingZone.h#L16-L19)
- [Constant.h](file://h/Constant.h#L80-L110)
## 详细组件分析
### CProManager::GetDMS 工厂实现
- 输入:DWORD dwHandle
- 关键步骤:
- 解析类型:uStyle = m_handleProcessor.GetStyleFromHandle(dwHandle)
- 查找缓存:pDMS = m_dmsLinkList.Get(dwHandle)
- 未命中则创建:根据 uStyle 创建 CProject 或 CTestingZone,构造参数包含 dwID 与数据库连接
- 加入缓存:m_dmsLinkList.Add(dwHandle, pDMS)
- 返回对象指针
- 类型识别:依赖 PZ_STYLE_PRO、PZ_STYLE_TZ 常量
- 缓存策略:按句柄键值缓存,避免重复创建,提升访问性能
```mermaid
flowchart TD
Start(["函数入口"]) --> ParseStyle["解析句柄类型(style)"]
ParseStyle --> Lookup["按句柄查找缓存"]
Lookup --> Found{"缓存命中?"}
Found --> |是| ReturnCached["返回缓存对象"]
Found --> |否| ParseID["解析ID(GetIDFromHandle)"]
ParseID --> SwitchStyle{"style分支"}
SwitchStyle --> |PZ_STYLE_PRO| NewProj["new CProject(ID, Connection)"]
SwitchStyle --> |PZ_STYLE_TZ| NewTZ["new CTestingZone(ID, Connection)"]
SwitchStyle --> |其他| Noop["不创建(保持空指针)"]
NewProj --> AddCache["加入缓存Add(dwHandle, pDMS)"]
NewTZ --> AddCache
Noop --> AddCache
AddCache --> ReturnObj["返回对象指针"]
ReturnCached --> End(["函数退出"])
ReturnObj --> End
```
图表来源
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
- [HandleProcessor.h](file://h/HandleProcessor.h#L17-L21)
- [LinkList.h](file://h/LinkList.h#L28-L31)
- [Project.h](file://h/Project.h#L18-L21)
- [TestingZone.h](file://h/TestingZone.h#L16-L19)
- [Constant.h](file://h/Constant.h#L80-L110)
章节来源
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
### 对象生命周期与缓存管理
- 生命周期控制:
- 构造:CProManager 构造时清空缓存
- 销毁:CProManager 析构时遍历并 delete 缓存中的对象,随后清空链表
- 删除:提供 DeleteObjInMem(dwHandle) 用于显式删除缓存对象
- 缓存一致性:
- CLinkList::Add 在添加前会检查重复(相同句柄或同一对象),避免重复
- CLinkList::Delete 支持按句柄或对象删除
- 作用:减少频繁创建销毁带来的开销,提升 UI 列表与详情展示的响应速度
```mermaid
classDiagram
class CProManager {
+GetDMS(dwHandle) CDataMngStruct*
+DeleteObjInMem(dwHandle) void
-m_dmsLinkList : CLinkList<CDataMngStruct*>
-m_handleProcessor : CHandleProcessor
}
class CHandleProcessor {
+GetStyleFromHandle(dwHandle) UINT
+GetIDFromHandle(dwHandle) DWORD
+GenerateHandle(dwID, uStyle) DWORD
}
class CLinkList~CDataMngStruct*~ {
+Get(dwHandle) CDataMngStruct*
+Add(dwHandle, data) bool
+Delete(dwHandle) bool
+DeleteAll() void
}
class CDataMngStruct {
<<abstract>>
+ShowDetailInfo(list) bool
}
class CProject {
+ShowDetailInfo(list) bool
-m_dwID : DWORD
}
class CTestingZone {
+ShowDetailInfo(list) bool
-m_dwID : DWORD
}
CProManager --> CHandleProcessor : "使用"
CProManager --> CLinkList : "缓存"
CDataMngStruct <|-- CProject
CDataMngStruct <|-- CTestingZone
```
图表来源
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [HandleProcessor.h](file://h/HandleProcessor.h#L12-L24)
- [LinkList.h](file://h/LinkList.h#L14-L43)
- [DataMngStruct.h](file://h/DataMngStruct.h#L14-L20)
- [Project.h](file://h/Project.h#L14-L21)
- [TestingZone.h](file://h/TestingZone.h#L12-L19)
章节来源
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [LinkList.h](file://h/LinkList.h#L14-L43)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L30-L51)
### 类型识别与扩展点
- 类型识别:通过 CHandleProcessor::GetStyleFromHandle 从句柄中提取 style,再在工厂中 switch 分支创建对应对象
- 扩展方式:新增类型只需在 switch 中添加新分支,并确保对应派生类已实现构造签名(ID, Connection
- 常量来源:PZ_STYLE_PRO、PZ_STYLE_TZ 等常量定义于 Constant.h
章节来源
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
- [HandleProcessor.h](file://h/HandleProcessor.h#L17-L21)
- [Constant.h](file://h/Constant.h#L80-L110)
### 实际调用场景与解耦效果
- 项目详情展示:CDataOperator::ShowProjectInfo 通过 GetDMS(dwProHandle) 获取 CProject 对象,调用其 ShowDetailInfo 展示项目信息,并联动测试数据列表
- 测区详情展示:CDataOperator::ShowTzInfo 通过 GetDMS(dwTzHandle) 获取 CTestingZone 对象,调用其 ShowDetailInfo 展示测区信息,并联动测试数据列表
- 解耦优势:
- 视图层仅依赖抽象接口(CDataMngStruct::ShowDetailInfo),不关心具体类型
- 工厂负责类型识别与对象创建,便于扩展新的管理对象类型
- 通过缓存降低重复创建成本,提升交互流畅度
```mermaid
sequenceDiagram
participant View as "视图/控制器"
participant DO as "CDataOperator"
participant PM as "CProManager"
participant DMS as "CDataMngStruct*"
participant PRJ as "CProject"
participant TZ as "CTestingZone"
View->>DO : 请求展示项目详情
DO->>PM : GetDMS(dwProHandle)
PM-->>DO : 返回 CDataMngStruct*
DO->>DMS : ShowDetailInfo(...)
alt 是项目
DMS-->>PRJ : 动态转换/调用
else 是测区
DMS-->>TZ : 动态转换/调用
end
DO->>PM : GetDMS(dwTzHandle)
PM-->>DO : 返回 CDataMngStruct*
DO->>DMS : ShowDetailInfo(...)
```
图表来源
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L488-L499)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
- [Project.h](file://h/Project.h#L18-L21)
- [TestingZone.h](file://h/TestingZone.h#L16-L19)
章节来源
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L488-L499)
## 依赖关系分析
- 组件耦合:
- CProManager 依赖 CHandleProcessor(解析句柄)、CLinkList(缓存)、CDataMngStruct(抽象基类)
- 具体派生类(CProject、CTestingZone)依赖数据库连接与ID,但对调用方透明
- 外部依赖:
- 数据库连接(_ConnectionPtr)贯穿对象构造,用于数据加载与持久化
- 循环依赖:
- 无直接循环依赖;工厂仅单向依赖句柄处理器与链表容器
```mermaid
graph LR
PM["CProManager"] --> HP["CHandleProcessor"]
PM --> LL["CLinkList<CDataMngStruct*>"]
PM --> DMS["CDataMngStruct"]
DMS --> PRJ["CProject"]
DMS --> TZ["CTestingZone"]
PM --> CST["Constant.h(PZ_STYLE_*)"]
```
图表来源
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [HandleProcessor.h](file://h/HandleProcessor.h#L12-L24)
- [LinkList.h](file://h/LinkList.h#L14-L43)
- [DataMngStruct.h](file://h/DataMngStruct.h#L14-L20)
- [Project.h](file://h/Project.h#L14-L21)
- [TestingZone.h](file://h/TestingZone.h#L12-L19)
- [Constant.h](file://h/Constant.h#L80-L110)
章节来源
- [ProManager.h](file://h/ProManager.h#L30-L74)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L181)
## 性能考量
- 时间复杂度:
- 缓存命中:O(1)
- 缓存未命中:O(n)(链表查找),n 为缓存长度
- 空间复杂度:O(n),n 为已创建对象数
- 优化建议:
- 优先保证高频访问对象的缓存命中率(例如项目/测区列表页)
- 控制缓存规模,必要时提供清理策略(如 DeleteObjInMem
- 对链表查找进行优化(如引入哈希映射)以降低查找成本
[本节为通用性能讨论,无需列出具体文件来源]
## 故障排查指南
- 常见问题与定位:
- 句柄无效或类型未知:GetStyleFromHandle 返回异常值,导致 switch 未匹配,返回空指针
- 缓存未命中但创建失败:检查构造参数(ID、Connection)是否有效
- 内存泄漏:确认析构时是否正确 delete 缓存对象
- 排查要点:
- 核对句柄生成与解析流程(GenerateHandle vs GetStyleFromHandle/GetIDFromHandle
- 检查链表 Add/Delete 行为,避免重复添加或遗漏删除
- 在调用方处对返回对象判空后再调用接口
章节来源
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L30-L51)
- [HandleProcessor.h](file://h/HandleProcessor.h#L17-L21)
- [LinkList.h](file://h/LinkList.h#L146-L182)
## 结论
CProManager::GetDMS 通过“工厂模式+缓存”的组合,实现了对 CDataMngStruct 派生对象的统一创建与管理。其关键价值在于:
- 类型识别与动态创建:基于句柄风格在运行时选择具体类型
- 缓存复用:显著降低对象创建成本,提升交互性能
- 接口解耦:调用方仅依赖抽象接口,便于扩展新的管理对象类型
- 生命周期可控:构造/析构与显式删除接口配合,保障资源释放
在“项目管理”与“测区管理”场景中,该工厂模式使视图层能够以一致的方式获取并展示对象详情,同时为后续扩展更多管理对象类型提供了清晰的扩展点与稳定的契约。
[本节为总结性内容,无需列出具体文件来源]
## 附录
- 代码片段路径参考(不展示具体代码内容):
- 工厂入口:[CProManager::GetDMS](file://cpp/Managers/ProManager.cpp#L154-L181)
- 句柄解析:[CHandleProcessor::GetStyleFromHandle](file://h/HandleProcessor.h#L17-L17)、[CHandleProcessor::GetIDFromHandle](file://h/HandleProcessor.h#L18-L18)
- 缓存容器:[CLinkList::Get/Add](file://h/LinkList.h#L28-L31)
- 抽象接口:[CDataMngStruct::ShowDetailInfo](file://h/DataMngStruct.h#L17-L17)
- 具体类型:[CProject](file://h/Project.h#L18-L21)、[CTestingZone](file://h/TestingZone.h#L16-L19)
- 类型常量:[PZ_STYLE_PRO/PZ_STYLE_TZ](file://h/Constant.h#L80-L110)
- 调用示例:[CDataOperator::ShowProjectInfo/ShowTzInfo](file://cpp/Operator/DataOperator.cpp#L488-L499)
[本节为补充说明,无需列出具体文件来源]
@@ -0,0 +1,151 @@
# 核心架构模式
<cite>
**本文档引用的文件**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
- [Global.cpp](file://cpp/Main/Global.cpp)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp)
- [GeoMative.h](file://h/GeoMative.h)
- [ProManager.h](file://h/ProManager.h)
- [DevManager.h](file://h/DevManager.h)
- [ExecManager.h](file://h/ExecManager.h)
</cite>
## 目录
1. [单例模式应用](#单例模式应用)
2. [工厂模式实现](#工厂模式实现)
3. [观察者模式机制](#观察者模式机制)
4. [责任链模式应用](#责任链模式应用)
5. [设计模式优势分析](#设计模式优势分析)
## 单例模式应用
在GeomativeStudio应用程序中,`CGeoMativeApp`类作为全局应用程序对象,通过继承MFC的`CWinApp`类实现单例模式。该模式确保在整个应用程序生命周期中只有一个`CGeoMativeApp`实例存在,从而集中管理全局资源和应用程序状态。
`CGeoMativeApp`类在`Global.cpp`文件中被声明为全局变量`theApp`,这是实现单例模式的关键。通过这种方式,应用程序的任何部分都可以通过`theApp`访问全局应用程序对象,而无需创建新的实例。这种设计确保了全局状态的一致性,并避免了资源的重复分配。
`GeoMative.cpp`文件中,`CGeoMativeApp`的构造函数初始化了多个管理器指针,包括`m_pTdManager``m_pProManager``m_pDevManager`等,这些指针在`InitInstance`方法中被实际创建。这种延迟初始化的策略优化了启动性能,只有在需要时才创建相应的管理器对象。
`CGeoMativeApp`类还负责管理数据库连接、网络操作、设备管理等核心功能。通过将这些功能集中在一个全局对象中,应用程序实现了资源的统一管理和访问控制。例如,`m_pConnection`成员变量提供了对数据库的全局访问,而`m_NetWorkOper`成员变量则管理所有的网络通信。
**Section sources**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L56-L130)
- [Global.cpp](file://cpp/Main/Global.cpp#L25-L26)
## 工厂模式实现
工厂模式在GeomativeStudio中主要通过`CProManager::GetDMS`方法实现,该方法根据句柄创建和管理不同类型的管理对象。这种设计模式将对象的创建逻辑与使用逻辑分离,提高了代码的灵活性和可维护性。
`CProManager`类中的`GetDMS`方法是一个典型的工厂方法实现。该方法接收一个句柄参数,根据句柄的样式(style)创建相应的数据管理结构对象。如果对象已经存在于缓存中,则直接返回缓存的对象;否则,根据句柄样式创建新的对象并将其添加到缓存中。
```mermaid
classDiagram
class CProManager {
+GetDMS(DWORD dwHandle) CDataMngStruct*
+ShowProList(DWORD dwDevHandle, CListCtrl& proList) bool
+ShowTzList(DWORD dwProHandle, CListCtrl& tzList) bool
+CreateProjectInDB(DWORD& dwID) UINT
+CreateProjectInDev(DWORD dwID, CDevice* const pDev) UINT
}
class CDataMngStruct {
<<abstract>>
+GetID() DWORD
+GetStyle() UINT
}
class CProject {
+CProject(DWORD dwID, _ConnectionPtr& pConnection)
+GetProjectName() CString
+GetProjectLocation() CString
}
class CTestingZone {
+CTestingZone(DWORD dwID, _ConnectionPtr& pConnection)
+GetZoneName() CString
+GetZoneType() CString
}
CProManager --> CDataMngStruct : "creates"
CDataMngStruct <|-- CProject : "extends"
CDataMngStruct <|-- CTestingZone : "extends"
```
**Diagram sources **
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L182)
- [ProManager.h](file://h/ProManager.h#L30-L74)
**Section sources**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L154-L182)
- [ProManager.h](file://h/ProManager.h#L30-L74)
## 观察者模式机制
观察者模式在GeomativeStudio中通过MFC消息映射(`DECLARE_MESSAGE_MAP`)和自定义WM_消息(如`WM_REFRESH``WM_SCHEDULE`)实现组件间的松耦合通信。这种设计模式允许对象在状态改变时通知其他对象,而无需知道这些对象的具体类型。
`GeoMative.h`文件中,`CGeoMativeApp`类使用`DECLARE_MESSAGE_MAP`宏声明了消息映射,这使得应用程序能够响应各种Windows消息。通过`BEGIN_MESSAGE_MAP``END_MESSAGE_MAP`宏,可以将特定的消息(如`ON_COMMAND`)映射到相应的处理函数。
自定义消息如`WM_REFRESH``WM_SCHEDULE`在应用程序的不同组件之间传递状态更新和调度信息。例如,在`datamngframe.cpp`文件中,`OnRefresh`方法处理`WM_REFRESH`消息,更新数据管理框架的视图。这种基于消息的通信机制使得组件之间的耦合度大大降低,每个组件只需关注自己感兴趣的消息。
```mermaid
sequenceDiagram
participant UI as "用户界面"
participant MainFrame as "主框架"
participant App as "CGeoMativeApp"
UI->>MainFrame : 用户操作
MainFrame->>App : 发送WM_SCHEDULE消息
App->>App : 处理消息映射
App->>MainFrame : 更新状态
MainFrame->>UI : 刷新界面
```
**Diagram sources **
- [GeoMative.h](file://h/GeoMative.h#L175-L176)
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L299-L312)
**Section sources**
- [GeoMative.h](file://h/GeoMative.h#L175-L176)
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L299-L312)
## 责任链模式应用
责任链模式在GeomativeStudio中应用于设备状态管理和任务执行流程。这种设计模式将请求的处理责任沿着一条链传递,直到某个处理者能够处理该请求。
在设备管理方面,`CDevManager`类通过`GetDevice``GetDeviceByID`方法实现了一条责任链。当请求获取设备时,系统会遍历设备链表,直到找到匹配的设备。如果设备未注册,系统会尝试通过序列号和MAC地址进行匹配。
在任务执行方面,`CExecManager`类的`Exec2DRSPTest``ExecCERSPTest`方法形成了一个责任链。这些方法负责执行不同的测试任务,每个方法都有明确的职责范围。如果一个方法无法处理某个任务,它会将请求传递给下一个方法。
```mermaid
flowchart TD
Start([开始]) --> CheckDevice["检查设备状态"]
CheckDevice --> DeviceValid{"设备有效?"}
DeviceValid --> |是| InitializeTest["初始化测试"]
DeviceValid --> |否| ReturnError["返回错误"]
InitializeTest --> ExecuteTest["执行测试"]
ExecuteTest --> ProcessResults["处理结果"]
ProcessResults --> UpdateStatus["更新状态"]
UpdateStatus --> End([结束])
ReturnError --> End
```
**Diagram sources **
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L82-L90)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp#L483-L613)
**Section sources**
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L82-L90)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp#L483-L613)
## 设计模式优势分析
GeomativeStudio中应用的这些设计模式显著提高了代码的可维护性和扩展性。单例模式确保了全局资源的一致性管理,避免了资源冲突和重复分配。工厂模式将对象创建逻辑集中管理,使得添加新的管理对象类型变得简单而安全。
观察者模式通过消息机制实现了组件间的松耦合通信,使得系统各部分可以独立开发和测试。这种设计大大降低了修改一个组件对其他组件的影响,提高了系统的稳定性和可维护性。
责任链模式为设备状态管理和任务执行提供了灵活的处理机制。通过将处理责任分解为多个步骤,系统能够更好地应对复杂的业务逻辑和异常情况。这种分层处理的方式也使得代码更易于理解和调试。
这些设计模式的综合应用,使得GeomativeStudio具有良好的架构特性:高内聚、低耦合、易于扩展和维护。当需要添加新功能或修改现有功能时,开发者可以专注于特定的组件或模式,而不必担心对整个系统造成意外影响。
**Section sources**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp)
@@ -0,0 +1,237 @@
# 观察者模式
<cite>
**本文档引用的文件**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp)
- [MainFrm.h](file://h/MainFrm.h)
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
- [devmngframe.h](file://h/devmngframe.h)
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp)
- [sptmngframe.cpp](file://cpp/Views/sptmngframe.cpp)
- [Constant.h](file://h/Constant.h)
- [NetWorkOper.cpp](file://cpp/Tools/NetWorkOper.cpp)
- [scheduler.cpp](file://cpp/Scheduler/scheduler.cpp)
- [StdThread.cpp](file://cpp/socket/StdThread.cpp)
</cite>
## 目录
1. [引言](#引言)
2. [MFC消息映射机制](#mfc消息映射机制)
3. [观察者模式实现分析](#观察者模式实现分析)
4. [自定义消息定义与使用](#自定义消息定义与使用)
5. [消息发送与处理流程](#消息发送与处理流程)
6. [组件间松耦合通信](#组件间松耦合通信)
7. [线程安全性与性能影响](#线程安全性与性能影响)
8. [结论](#结论)
## 引言
本项目采用MFC框架实现了一个地质探测软件系统,通过MFC的消息映射机制实现了观察者模式。该模式允许UI组件通过消息映射注册对特定事件的兴趣,从而实现组件间的松耦合通信。系统通过DECLARE_MESSAGE_MAP宏和AFX_MSG消息处理机制,结合自定义消息WM_SCHEDULE和WM_REFRESH,实现了界面刷新和任务调度等功能。
**Section sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L1-L2362)
- [MainFrm.h](file://h/MainFrm.h#L1-L120)
## MFC消息映射机制
MFC消息映射机制是实现观察者模式的核心。在MFC中,DECLARE_MESSAGE_MAP宏用于声明消息映射表,而BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏则用于定义消息映射的具体内容。通过这种机制,UI组件可以注册对特定消息的处理函数。
在MainFrm类中,消息映射的定义如下:
```mermaid
classDiagram
class CMainFrame {
+DECLARE_DYNAMIC(CMainFrame)
+BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
+ON_WM_CREATE()
+ON_COMMAND(IDM_MNG_DATA_WIN, OnMngDataWin)
+ON_COMMAND(IDM_MNG_EXEC_WIN, OnMngExecWin)
+ON_COMMAND(IDM_MNG_DEV_WIN, OnMngDevWin)
+ON_MESSAGE(WM_SCHEDULE, OnSchedule)
+ON_MESSAGE(WM_REFRESH, OnRefresh)
+END_MESSAGE_MAP()
}
```
**Diagram sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L58-L94)
**Section sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L58-L94)
- [MainFrm.h](file://h/MainFrm.h#L19-L97)
## 观察者模式实现分析
观察者模式在本项目中通过消息映射机制实现。UI组件通过消息映射注册对特定事件的兴趣,当事件发生时,系统会自动调用相应的处理函数。
以MainFrm和DevMngFrame为例,它们之间的观察者关系如下:
```mermaid
sequenceDiagram
participant MainFrm as CMainFrame
participant DevMngFrame as CDevMngFrame
MainFrm->>DevMngFrame : SendMessage(WM_REFRESH_NAV_DEVICE)
DevMngFrame->>DevMngFrame : OnRefreshNavDevice()
DevMngFrame->>MainFrm : SendMessage(WM_SCHEDULE)
MainFrm->>MainFrm : OnSchedule()
```
**Diagram sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L323-L324)
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp#L593-L596)
**Section sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L323-L324)
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp#L593-L596)
## 自定义消息定义与使用
项目中定义了多个自定义消息,用于实现特定的业务逻辑。这些消息在Constant.h文件中定义:
```mermaid
erDiagram
CUSTOM_MESSAGE {
int WM_SCHEDULE PK
int WM_REFRESH
int WM_NEWLINK
int WM_BREAKLINE
int WM_UPG_GEOMATIVE
int WM_REFRESH_NAV_DEVICE
int WM_SHOW_DEV_UPG_INFO
int WM_CLEAR_DEV_UPG_INFO
}
```
**Diagram sources**
- [Constant.h](file://h/Constant.h#L182-L191)
**Section sources**
- [Constant.h](file://h/Constant.h#L182-L191)
### WM_SCHEDULE消息
WM_SCHEDULE消息用于任务调度,由MainFrm类处理:
```mermaid
flowchart TD
Start([开始]) --> CheckScheduler["检查调度器"]
CheckScheduler --> ExecuteScheduler["执行调度任务"]
ExecuteScheduler --> InvalidateToolbar["无效化工具栏"]
InvalidateToolbar --> ShowToolbar["显示工具栏"]
ShowToolbar --> End([结束])
```
**Diagram sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L581-L588)
**Section sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L581-L588)
### WM_REFRESH消息
WM_REFRESH消息用于界面刷新,支持多种刷新类型:
```mermaid
classDiagram
class CMainFrame {
+OnRefresh(WPARAM wParam, LPARAM lParam)
}
class RefreshType {
+OP_FILE_IMP
+OP_TD_SYN
+OP_SPT_SYN
+OP_DE_F_D
}
CMainFrame --> RefreshType : "使用"
```
**Diagram sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L590-L619)
- [Constant.h](file://h/Constant.h#L202-L207)
**Section sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L590-L619)
## 消息发送与处理流程
消息的发送与处理流程是观察者模式的关键。系统使用SendMessage和PostMessage函数来发送消息,并通过消息映射机制进行处理。
消息处理流程如下:
```mermaid
sequenceDiagram
participant Sender as 发送者
participant MessageQueue as 消息队列
participant Receiver as 接收者
Sender->>MessageQueue : PostMessage()
MessageQueue->>Receiver : 消息入队
Receiver->>Receiver : PeekMessage()
Receiver->>Receiver : TranslateMessage()
Receiver->>Receiver : DispatchMessage()
Receiver->>Receiver : 调用消息处理函数
```
**Diagram sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L323-L324)
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp#L593-L596)
**Section sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L323-L324)
## 组件间松耦合通信
通过消息映射机制,系统实现了组件间的松耦合通信。各组件通过发送和接收消息进行交互,而不需要直接引用对方。
组件间通信关系如下:
```mermaid
graph TB
subgraph "主框架"
MainFrm[CMainFrame]
end
subgraph "管理框架"
DevMngFrame[CDevMngFrame]
DataMngFrame[CDataMngFrame]
SptMngFrame[CSptMngFrame]
end
MainFrm --> |WM_REFRESH| DataMngFrame
MainFrm --> |WM_SCHEDULE| DevMngFrame
MainFrm --> |WM_SCHEDULE| SptMngFrame
DevMngFrame --> |WM_SCHEDULE| MainFrm
DataMngFrame --> |WM_REFRESH| MainFrm
```
**Diagram sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L597-L615)
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp#L237-L238)
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L87-L89)
**Section sources**
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L597-L615)
## 线程安全性与性能影响
系统的线程安全性和性能影响主要体现在网络操作和消息处理上。NetWorkOper类负责处理网络通信,通过线程安全的机制确保消息的正确传递。
线程安全机制如下:
```mermaid
classDiagram
class CNetWorkOper {
+RegeditRealMsgCall(HWND hWnd)
+UnRegeditRealMsgCall(HWND hWnd)
+ThreadFunction()
+m_listRealHwnd list<HWND>
+m_realHwndCs CRITICAL_SECTION
}
class CAutoLock {
+CAutoLock(CRITICAL_SECTION* pCs)
+~CAutoLock()
}
CNetWorkOper --> CAutoLock : "使用"
CNetWorkOper --> CRITICAL_SECTION : "保护"
```
**Diagram sources**
- [NetWorkOper.cpp](file://cpp/Tools/NetWorkOper.cpp#L343-L364)
- [StdThread.cpp](file://cpp/socket/StdThread.cpp#L1-L228)
**Section sources**
- [NetWorkOper.cpp](file://cpp/Tools/NetWorkOper.cpp#L343-L364)
## 结论
本项目通过MFC消息映射机制成功实现了观察者模式。系统使用DECLARE_MESSAGE_MAP宏和AFX_MSG消息处理机制,使UI组件能够注册对特定事件的兴趣。自定义消息WM_SCHEDULE和WM_REFRESH的定义与使用,实现了界面刷新和任务调度功能。通过SendMessage和PostMessage函数,系统实现了组件间的松耦合通信。在MainFrm、DevMngFrame等类的实际应用中,观察者模式有效地管理了界面状态和用户交互。尽管存在一定的线程安全性考虑,但通过临界区保护和线程同步机制,系统能够稳定运行。这种设计模式提高了代码的可维护性和可扩展性,为系统的持续发展奠定了良好基础。
@@ -0,0 +1,239 @@
# 责任链模式
<cite>
**本文档引用的文件**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
- [HandleProcessor.cpp](file://cpp/Tools/HandleProcessor.cpp)
- [StateProcessor.cpp](file://cpp/Tools/StateProcessor.cpp)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
- [Constant.h](file://h/Constant.h)
- [ProManager.h](file://h/ProManager.h)
- [DevManager.h](file://h/DevManager.h)
- [HandleProcessor.h](file://h/HandleProcessor.h)
- [StateProcessor.h](file://h/StateProcessor.h)
- [ExecManager.h](file://h/ExecManager.h)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
本文档深入剖析责任链模式在Geomative Studio软件中的设备状态管理和任务执行流程中的应用。该系统通过CProManager、CDevManager等管理器形成处理链条,逐级传递和处理设备操作请求。CHandleProcessor和CStateProcessor在状态流转中扮演关键角色,确保请求在链条中按条件传递并适时终止。结合设备连接、任务配置等业务流程,责任链模式实现了关注点分离和灵活的处理逻辑扩展。文档还将通过代码示例说明异常处理和状态回滚的实现方式。
## 项目结构
Geomative Studio项目采用分层模块化设计,主要分为核心管理器、工具类和问题区域三大模块。核心管理器(Managers)包含CProManager、CDevManager等,负责工程和设备的生命周期管理。工具类(Tools)提供CHandleProcessor和CStateProcessor等通用服务,用于句柄生成和状态转换。问题区域(ProblemZone)则包含具体的业务实体如CDevice。这种结构清晰地分离了关注点,为责任链模式的应用提供了基础。
```mermaid
graph TB
subgraph "核心管理器"
ProManager[CProManager]
DevManager[CDevManager]
ExecManager[CExecManager]
end
subgraph "工具类"
HandleProcessor[CHandleProcessor]
StateProcessor[CStateProcessor]
end
subgraph "问题区域"
Device[CDevice]
end
ProManager --> HandleProcessor
DevManager --> HandleProcessor
ExecManager --> HandleProcessor
ProManager --> StateProcessor
DevManager --> Device
ExecManager --> Device
```
**图源**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L32-L37)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L24-L28)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp#L49-L53)
- [HandleProcessor.cpp](file://cpp/Tools/HandleProcessor.cpp#L19-L27)
- [StateProcessor.cpp](file://cpp/Tools/StateProcessor.cpp#L19-L27)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L42-L48)
**节源**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L1-L50)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L1-L50)
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp#L1-L50)
## 核心组件
系统的核心组件包括CProManager、CDevManager、CHandleProcessor和CStateProcessor。CProManager负责工程和测区的创建、删除及与设备的同步。CDevManager管理设备的注册、状态更新和在线/离线设备列表。CHandleProcessor提供句柄生成和解析功能,将ID和类型信息编码到32位整数中。CStateProcessor则负责UI状态与内部状态之间的转换。这些组件通过责任链模式协同工作,确保操作请求能够被正确路由和处理。
**节源**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L32-L40)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L24-L31)
- [HandleProcessor.cpp](file://cpp/Tools/HandleProcessor.cpp#L19-L27)
- [StateProcessor.cpp](file://cpp/Tools/StateProcessor.cpp#L19-L27)
## 架构概述
系统采用责任链模式构建了一个分层的处理架构。当用户发起一个设备操作请求时,请求首先被CProManager接收。CProManager根据请求类型,可能需要与CDevManager协作,获取目标设备的句柄和状态。CHandleProcessor负责将设备ID和类型信息编码成唯一的句柄,而CStateProcessor则确保设备的当前状态(如在线、离线、新设备)在UI和内部逻辑之间正确映射。整个链条确保了请求的有序传递和处理。
```mermaid
sequenceDiagram
participant User as "用户"
participant ProManager as "CProManager"
participant DevManager as "CDevManager"
participant HandleProcessor as "CHandleProcessor"
participant Device as "CDevice"
User->>ProManager : 创建工程请求
ProManager->>DevManager : 获取设备句柄
DevManager->>HandleProcessor : 生成设备句柄
HandleProcessor-->>DevManager : 返回句柄
DevManager-->>ProManager : 返回设备对象
ProManager->>Device : 执行设备操作
Device-->>ProManager : 操作结果
ProManager-->>User : 操作完成通知
```
**图源**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L249-L317)
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L82-L90)
- [HandleProcessor.cpp](file://cpp/Tools/HandleProcessor.cpp#L29-L42)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L42-L48)
## 详细组件分析
### CProManager 分析
CProManager是工程管理的核心,负责工程和测区的全生命周期管理。它通过责任链模式与其他组件交互,确保操作的原子性和一致性。
#### 工程创建流程
```mermaid
flowchart TD
Start([开始创建工程]) --> ValidateInput["验证输入参数"]
ValidateInput --> InputValid{"输入有效?"}
InputValid --> |否| ReturnError["返回错误"]
InputValid --> |是| CheckExist["检查工程名是否存在"]
CheckExist --> Exist{"已存在?"}
Exist --> |是| HandleDuplicate["提示名称重复"]
Exist --> |否| InsertDB["插入数据库"]
InsertDB --> CreateDev["在设备上创建工程"]
CreateDev --> Success{"成功?"}
Success --> |是| UpdateSync["更新同步状态"]
Success --> |否| Rollback["回滚数据库事务"]
UpdateSync --> End([工程创建完成])
Rollback --> End
HandleDuplicate --> End
ReturnError --> End
```
**图源**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L249-L317)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L343-L483)
**节源**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L249-L483)
### CDevManager 分析
CDevManager负责设备的注册、状态管理和列表维护。它通过责任链模式与CProManager和设备对象交互。
#### 设备状态管理
```mermaid
classDiagram
class CDevManager {
+_ConnectionPtr m_pConnection
+CLinkList<CDevice*> m_devLinkList
+CHandleProcessor m_handleProcessor
+GetDevice(DWORD dwHandle) CDevice*
+GetDevice(CString szDevSN) CDevice*
+InitialDevLinkList() void
+AddDevice(CDevice* const pDev) BOOL
+DeleteDevice(DWORD dwHandle) BOOL
}
class CDevice {
+DWORD m_dwID
+UINT m_uState
+UINT m_uType
+CString m_szDevSN
+CString m_szMacAddress
+SetState(UINT uState) void
+SetID(DWORD dwID) void
}
class CHandleProcessor {
+GenerateHandle(DWORD dwID, UINT uStyle) DWORD
+GetIDFromHandle(DWORD dwHandle) DWORD
+GetStyleFromHandle(DWORD dwHandle) UINT
}
CDevManager --> CDevice : "管理"
CDevManager --> CHandleProcessor : "使用"
CDevice <|-- CDevice : "自身"
```
**图源**
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L24-L31)
- [DevManager.h](file://h/DevManager.h#L16-L69)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L42-L48)
- [HandleProcessor.cpp](file://cpp/Tools/HandleProcessor.cpp#L19-L27)
**节源**
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp#L24-L400)
### CHandleProcessor 和 CStateProcessor 分析
这两个工具类是责任链模式的基础,提供句柄处理和状态转换服务。
#### 句柄处理机制
```mermaid
flowchart LR
ID[设备ID] --> Shift["左移27位"]
Style[类型] --> Shift
Shift --> Combine["与操作"]
Combine --> Handle[32位句柄]
Handle --> Extract["提取"]
Extract --> ID2["ID (低27位)"]
Extract --> Style2["类型 (高5位)"]
```
**图源**
- [HandleProcessor.cpp](file://cpp/Tools/HandleProcessor.cpp#L29-L42)
- [HandleProcessor.h](file://h/HandleProcessor.h#L18-L23)
**节源**
- [HandleProcessor.cpp](file://cpp/Tools/HandleProcessor.cpp#L29-L96)
## 依赖分析
系统各组件之间存在明确的依赖关系。CProManager依赖于CDevManager来获取设备信息,两者都依赖于CHandleProcessor进行句柄处理。CStateProcessor被多个管理器使用,以实现状态的统一管理。这种依赖结构形成了一个清晰的责任链,每个组件只关心自己的职责,通过接口与上下游组件通信。
```mermaid
graph LR
ProManager --> DevManager
ProManager --> HandleProcessor
ProManager --> StateProcessor
DevManager --> HandleProcessor
DevManager --> Device
ExecManager --> HandleProcessor
ExecManager --> Device
```
**图源**
- [ProManager.h](file://h/ProManager.h#L65-L68)
- [DevManager.h](file://h/DevManager.h#L27-L28)
- [ExecManager.h](file://h/ExecManager.h#L36-L38)
**节源**
- [ProManager.h](file://h/ProManager.h#L1-L77)
- [DevManager.h](file://h/DevManager.h#L1-L69)
- [ExecManager.h](file://h/ExecManager.h#L1-L42)
## 性能考虑
责任链模式的应用对系统性能有重要影响。句柄的生成和解析是轻量级的位运算,对性能影响极小。然而,数据库操作和文件传输是潜在的性能瓶颈。系统通过事务管理确保数据一致性,并在文件传输失败时进行状态回滚。建议在高并发场景下对数据库连接进行池化管理,并优化文件传输协议以减少延迟。
## 故障排除指南
当系统出现异常时,应首先检查设备状态和网络连接。责任链中的每个环节都应有完善的异常处理机制。例如,CProManager在创建工程时,如果设备操作失败,会回滚数据库事务,确保数据一致性。日志文件(如device_log.txt)是诊断问题的重要依据,应定期检查。
**节源**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L262-L317)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L58-L66)
## 结论
责任链模式在Geomative Studio系统中得到了有效应用,通过CProManager、CDevManager等管理器的协作,实现了设备状态管理和任务执行流程的清晰分离。CHandleProcessor和CStateProcessor作为基础工具,为整个链条提供了可靠的服务。该设计不仅提高了代码的可维护性和可扩展性,还通过事务管理和异常处理机制保证了系统的稳定性和数据一致性。