Solution: Decorator

Decorated Sensor (Intermediate Interface)

#pragma once

#include <sensor.h>

#include <string>
#include <memory>


class DecoratedSensor : public Sensor
{
public:
    DecoratedSensor(const std::string& name)
    : _name(name) {}

    const std::string& name() const { return _name; }
    virtual std::string description() const = 0;

private:
    std::string _name;
};

Decorated Constant Sensor

#pragma once

#include "sensor-decorated.h"
#include "sensor-const.h"


class DecoratedConstantSensor : public DecoratedSensor
{
public:
    DecoratedConstantSensor(const std::string& name, double temperature)
    : DecoratedSensor(name),
      _sensor(temperature) {}

    virtual std::string description() const override;
    virtual double get_temperature() { return _sensor.get_temperature(); }

private:
    ConstantSensor _sensor;
};
#include "sensor-decorated-const.h"

#include <sstream>
#include <iomanip>


std::string DecoratedConstantSensor::description() const
{
    std::ostringstream buffer;
    buffer << "ConstantSensor(" << _sensor.value() << ')';
    return buffer.str();
}

Decorated Random Sensor

#pragma once

#include "sensor-decorated.h"
#include "sensor-random.h"


class DecoratedRandomSensor : public DecoratedSensor
{
public:
    DecoratedRandomSensor(const std::string& name, double low, double high)
    : DecoratedSensor(name),
      _sensor(low, high) {}

    virtual std::string description() const override;
    virtual double get_temperature() { return _sensor.get_temperature(); }

private:
    RandomSensor _sensor;
};
#include "sensor-decorated-random.h"

#include <sstream>
#include <iomanip>


std::string DecoratedRandomSensor::description() const
{
    std::ostringstream buffer;
    buffer << "RandomSensor(" << _sensor.low() << ", " << _sensor.high() << ')';
    return buffer.str();
}