在动平衡仪的使用过程中,配置参数的动态切换(如切换传感器通道、切换单位)需要实时反映在界面显示和计算方法上。为了实现这种动态响应,可以采用 观察者模式(Observer Pattern) 和 事件驱动架构(Event-Driven Architecture),并结合分层架构设计。以下是详细的设计思路和实现方法:
1. 设计思路
跳转到“1. 设计思路”1.1 核心需求
跳转到“1.1 核心需求”- 动态响应:当配置参数(如单位、传感器通道、结果显示选项)发生变化时,相关界面和功能需要实时更新。
- 解耦:配置管理模块与其他模块(如界面、算法、传感器管理)之间应保持低耦合。
- 可扩展性:新增配置项或功能时,不应影响现有代码。
1.2 设计模式
跳转到“1.2 设计模式”- 观察者模式:
- 配置管理模块作为被观察者(Subject),其他模块(如界面、算法、传感器管理)作为观察者(Observer)。
- 当配置参数发生变化时,配置管理模块通知所有观察者。
- 事件驱动架构:
- 使用事件机制传递配置变化的消息,进一步解耦模块之间的依赖。
1.3 分层架构
跳转到“1.3 分层架构”- 用户界面层(UI Layer):
- 负责显示配置界面和动平衡界面。
- 监听配置变化事件,动态更新界面。
- 业务逻辑层(Business Logic Layer):
- 负责动平衡算法、传感器管理等功能。
- 监听配置变化事件,动态调整算法和传感器通道。
- 数据访问层(Data Access Layer):
- 负责配置参数的持久化(保存和加载)。
- 配置管理层(Configuration Layer):
- 集中管理所有配置项。
- 提供接口供其他模块读取和修改配置。
- 触发配置变化事件。
2. 体系结构设计
跳转到“2. 体系结构设计”2.1 模块划分
跳转到“2.1 模块划分”- 配置管理模块:
- 管理所有配置项(如单位、传感器通道、结果显示选项)。
- 提供接口供其他模块读取和修改配置。
- 触发配置变化事件。
- 持久化模块:
- 负责将配置参数保存到文件或数据库中,并在启动时加载。
- 界面模块:
- 显示配置界面和动平衡界面。
- 监听配置变化事件,动态更新界面。
- 算法模块:
- 根据单位配置调用不同的算法。
- 监听配置变化事件,动态调整算法。
- 传感器管理模块:
- 根据传感器通道设置开启或关闭传感器通道。
- 监听配置变化事件,动态调整传感器通道。
2.2 层次结构
跳转到“2.2 层次结构”+-------------------+| 用户界面层 (UI) |+-------------------+| - 配置界面 || - 动平衡界面 |+-------------------+ | v+-------------------+| 业务逻辑层 (BL) |+-------------------+| - 算法模块 || - 传感器管理模块 |+-------------------+ | v+-------------------+| 配置管理层 (CL) |+-------------------+| - 配置管理模块 || - 持久化模块 |+-------------------+3. 实现方法
跳转到“3. 实现方法”3.1 配置管理模块
跳转到“3.1 配置管理模块”配置管理模块使用观察者模式,当配置参数发生变化时,通知所有观察者。
#ifndef CONFIGMANAGER_H#define CONFIGMANAGER_H
#include <QObject>#include <QMap>
class ConfigManager : public QObject { Q_OBJECT
public: enum class Unit { Grams, Ounces, Millimeters, Inches }; enum class DisplayOption { Amplitude, Phase, RPM };
ConfigManager(QObject* parent = nullptr);
void setUnit(Unit unit); Unit getUnit() const;
void setSensorChannels(const QMap<int, bool>& channels); QMap<int, bool> getSensorChannels() const;
void setDisplayOptions(const QMap<DisplayOption, bool>& options); QMap<DisplayOption, bool> getDisplayOptions() const;
signals: void unitChanged(Unit unit); void sensorChannelsChanged(const QMap<int, bool>& channels); void displayOptionsChanged(const QMap<DisplayOption, bool>& options);
private: Unit m_unit; QMap<int, bool> m_sensorChannels; QMap<DisplayOption, bool> m_displayOptions;};
#endif // CONFIGMANAGER_H#include "ConfigManager.h"
ConfigManager::ConfigManager(QObject* parent) : QObject(parent), m_unit(Unit::Grams) {}
void ConfigManager::setUnit(Unit unit) { if (m_unit != unit) { m_unit = unit; emit unitChanged(unit); }}
ConfigManager::Unit ConfigManager::getUnit() const { return m_unit;}
void ConfigManager::setSensorChannels(const QMap<int, bool>& channels) { if (m_sensorChannels != channels) { m_sensorChannels = channels; emit sensorChannelsChanged(channels); }}
QMap<int, bool> ConfigManager::getSensorChannels() const { return m_sensorChannels;}
void ConfigManager::setDisplayOptions(const QMap<DisplayOption, bool>& options) { if (m_displayOptions != options) { m_displayOptions = options; emit displayOptionsChanged(options); }}
QMap<ConfigManager::DisplayOption, bool> ConfigManager::getDisplayOptions() const { return m_displayOptions;}3.2 界面模块
跳转到“3.2 界面模块”界面模块监听配置变化事件,动态更新界面。
#ifndef BALANCINGUI_H#define BALANCINGUI_H
#include <QWidget>#include "ConfigManager.h"
class BalancingUI : public QWidget { Q_OBJECT
public: BalancingUI(ConfigManager* configManager, QWidget* parent = nullptr);
private slots: void onUnitChanged(ConfigManager::Unit unit); void onDisplayOptionsChanged(const QMap<ConfigManager::DisplayOption, bool>& options);
private: ConfigManager* m_configManager; QLabel* m_unitLabel; QLabel* m_amplitudeLabel; QLabel* m_phaseLabel; QLabel* m_rpmLabel;};
#endif // BALANCINGUI_H#include "BalancingUI.h"#include <QVBoxLayout>
BalancingUI::BalancingUI(ConfigManager* configManager, QWidget* parent) : QWidget(parent), m_configManager(configManager) { m_unitLabel = new QLabel(this); m_amplitudeLabel = new QLabel(this); m_phaseLabel = new QLabel(this); m_rpmLabel = new QLabel(this);
QVBoxLayout* layout = new QVBoxLayout(this); layout->addWidget(m_unitLabel); layout->addWidget(m_amplitudeLabel); layout->addWidget(m_phaseLabel); layout->addWidget(m_rpmLabel); setLayout(layout);
// 监听配置变化事件 connect(m_configManager, &ConfigManager::unitChanged, this, &BalancingUI::onUnitChanged); connect(m_configManager, &ConfigManager::displayOptionsChanged, this, &BalancingUI::onDisplayOptionsChanged);
// 初始化界面 onUnitChanged(m_configManager->getUnit()); onDisplayOptionsChanged(m_configManager->getDisplayOptions());}
void BalancingUI::onUnitChanged(ConfigManager::Unit unit) { QString unitText = (unit == ConfigManager::Unit::Grams) ? "Grams" : "Ounces"; m_unitLabel->setText("Unit: " + unitText);}
void BalancingUI::onDisplayOptionsChanged(const QMap<ConfigManager::DisplayOption, bool>& options) { if (options[ConfigManager::DisplayOption::Amplitude]) { m_amplitudeLabel->setText("Amplitude: 10.5"); } else { m_amplitudeLabel->clear(); } if (options[ConfigManager::DisplayOption::Phase]) { m_phaseLabel->setText("Phase: 45°"); } else { m_phaseLabel->clear(); } if (options[ConfigManager::DisplayOption::RPM]) { m_rpmLabel->setText("RPM: 3000"); } else { m_rpmLabel->clear(); }}3.3 算法模块
跳转到“3.3 算法模块”算法模块监听单位配置变化事件,动态调整算法。
#ifndef BALANCINGALGORITHM_H#define BALANCINGALGORITHM_H
#include "ConfigManager.h"
class BalancingAlgorithm {public: BalancingAlgorithm(ConfigManager* configManager);
private slots: void onUnitChanged(ConfigManager::Unit unit);
private: ConfigManager* m_configManager;};
#endif // BALANCINGALGORITHM_H#include "BalancingAlgorithm.h"
BalancingAlgorithm::BalancingAlgorithm(ConfigManager* configManager) : m_configManager(configManager) { connect(m_configManager, &ConfigManager::unitChanged, this, &BalancingAlgorithm::onUnitChanged);}
void BalancingAlgorithm::onUnitChanged(ConfigManager::Unit unit) { switch (unit) { case ConfigManager::Unit::Grams: // 调用克单位的算法 break; case ConfigManager::Unit::Ounces: // 调用盎司单位的算法 break; }}4. 总结
跳转到“4. 总结”通过观察者模式和事件驱动架构,可以实现配置参数的动态切换,并确保相关界面和功能实时更新。这种设计具有以下优势:
- 解耦:各模块通过事件交互,降低耦合度。
- 动态响应:配置变化实时反映在界面和功能上。
- 可扩展性:新增配置项或功能时,只需添加新的观察者即可。
如果需要更详细的实现或工具使用指导,可以进一步探讨!
来源:CSDN 原文,首次发布于 2025-03-10。