a
This commit is contained in:
@@ -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的职责划分清晰,配合管理器集合的创建与持有,为全应用提供了稳定的全局访问入口。实践中应注意线程安全、资源竞争与依赖膨胀等问题,以确保系统的健壮性与可维护性。
|
||||
Reference in New Issue
Block a user