【问题标题】:OOP for global system/task monitoring class面向全局系统/任务监控类的 OOP
【发布时间】:2019-06-07 16:19:56
【问题描述】:

我正在尝试创建各种性能监视器以在刨花板(基于 STM32)上运行。我习惯用 c 编程,所以 OOP 方法有点新,但我认为它很适合这里。

出于这个问题的目的,假设我有两种类型的监视器:

  1. 频率。应用程序可以调用监视器的“tick”方法来计算自上次运行以来的时间并将其存储。
  2. Period - 调用监视器的“开始”和“停止”方法来计算进程运行和存储所需的时间。

我想做的是在整个应用程序中创建这些监视器的实例,并能够从主模块报告所有类型的所有监视器的统计信息。

我读过单例设计模式,这似乎是我需要的,但我不确定,我也担心线程安全。

我想我将创建一个“StatMonitor”类和一个派生类“FrequencyMonitor”和“PeriodMonitor”。 Monitor 将是一个单例,在任何我想创建一个新监视器的地方我都会请求一个“Monitor”实例并像这样使用它:

freqMonitor * task1FreqMonitor = StatMonitor::GetInstance()->Add_Freq_Monitor("Task1");

StatMonitor 将跟踪我添加的所有监视器,当我想打印统计信息时,我可以调用 printAll 方法,该方法将迭代它的监视器数组并请求它们的结果,如下所示:

StatMonitor::GetInstance()->PrintAllStats();

我走在正确的道路上吗?

【问题讨论】:

  • 您可以创建一个 Registrar Singleton,允许注册和检索特定类型的监视器。
  • 另一种选择是使用 Abstract Factory 设计模式。

标签: c++ class oop


【解决方案1】:

您的路径听起来不错,除了 FrequencyMonitorPeriodMonitor 不应派生自“管理”所有这些监视器的类(我们称之为 MonitorPrinter)。

MonitorPrinter 应该是一个单例,看起来像这样:

class MonitorPrinter
{
public:
    static MonitorPrinter& getInstance()
    {
        static MonitorPrinter monitorPrinter;
        return monitorPrinter;
    }

    void printAllStats()
    {
        for (const auto& [_, frequencyMonitor] : _frequencyMonitors)
            frequencyMonitor.print();
        for (const auto& [_, periodMonitor] : _periodMonitors)
            periodMonitor.print();
    }

    FrequencyMonitor& getFrequencyMonitor(std::string name)
    { return _frequencyMonitors[name]; }
    PeriodMonitor& getPeriodMonitor(std::string name)
    { return _periodMonitors[name]; }

private:
    MonitorPrinter() = default;

    std::map<std::string, FrequencyMonitor> _frequencyMonitors;
    std::map<std::string, PeriodMonitor> _periodMonitors;
};

Demo

const auto&amp; [_, frequencyMonitor]structured binding)。

FrequencyMonitorPeriodMonitor 不应该与单例有任何关系,根据您的描述,它们也不需要是类层次结构的一部分(因为它们具有不同的接口)。如果您愿意,您可以阻止用户(MonitorPrinter 除外)使用其他技术实例化这些类,但我不会在这里详细说明。

总之,这里没有必要使用OOP。使用单例来提供(并跟踪)监视器,并根据自己的喜好实现监视器。如果这是相关的,请注意线程安全(以上不是线程安全的!)。

【讨论】:

  • 监控器的界面中可能会有一些常用方法(重置统计信息、获取统计信息等)。那么拥有层次结构是否有意义或没有任何好处?
  • 是的,在这种情况下,层次结构是有意义的。但是没有理由让基类也成为单例——MonitorPrinter 的接口和用途与各个监视器(及其潜在的基类)完全不同。
  • @spizzak FrequencyMonitorPeriodMonitor 派生自 Monitor 的情况,但我不确定我是否看到他们中的任何一个也必须在这里申请。试一试几个选项,看看最适合您的选项。
  • 别忘了我们的好朋友Liskov Substitution Principle
  • @MaxLanghof,我决定只创建一个监视器来跟踪这两个统计数据,因为这将满足我的需求。现在的计划是有一个像 MonitorPrinter 这样的单例“监视器管理器”来根据需要提供监视器。我不确定的是您如何在示例中提供监视器。这里创建的监控对象在哪里?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多