一、需求分析
需求:一个温度计类或程序,用于读取某些外部源的温度。
a - 温度计需要能够提供华氏温度和摄氏温度。
b - 类的调用者必须可以定义任意阈值,例如冻结和沸腾,在这些阈值温度计类将通知适当的调用者已达到特定阈值。 请注意,如果温度在阈值点附近波动,则类的调用者可能不希望被重复告知已达到给定阈值。 例如,考虑以下温度来自外部来源的读数:
1.5 C,1.0 C,0.5 C,0.0 C,-0.5 C,0.0 C,-0.5 C,0.0 C,0.5 C,0.0C
有些调用者可能只想知道温度达到 0° C 一次,因为他们认为 +/- 0.5° C 的波动微不足道。
c - 仅当从某个方向达到阈值时才通知一些调用者已经达到阈值对于一些调用者来说可能也是重要的。 例如,如果之前的温度高于冰点,一些调用者可能只关心冰点阈值(即他们只关心在温度下降时发生的阈值)。
二、代码实现
1、通过readTemperature接口读取外部温度、阈值、是否只通知下降方向、温度转换类型;
void TemperatureGauge::readTemperature(vector<double> currentTemperature, double threshold, bool isOnlyDownDirction, TempeType type)
{
switch (type)
{
case NO_TEMP_TRANSFORM:
for (int i = 0; i < currentTemperature.size(); i++)
{
notifyAtThreshold(currentTemperature[i], threshold, isOnlyDownDirction, NO_TEMP_TRANSFORM);
}
break;
case CELSIUS_TEMP_TO_FAHR:
for (int i = 0; i < currentTemperature.size(); i++)
{
double fahr = currentTemperature[i] * 1.8 + 32;
double fahrThreshold = threshold * 1.8 + 32;
notifyAtThreshold(fahr, fahrThreshold, isOnlyDownDirction, CELSIUS_TEMP_TO_FAHR);
}
break;
default:
break;
}
}
2、内部通过notifyAtThreshold接口通知调用者到达设定阈值
void TemperatureGauge::notifyAtThreshold(double currentTemperature, double threshold, bool isOnlyDownDirction, TempeType type)
{
double rang = (type == CELSIUS_TEMP_TO_FAHR ? 0.9 : 0.5);
if (currentTemperature == threshold && flag)
{
cout << "Current temperature is reach threshold." << endl;
flag = false;
}
else if (currentTemperature - threshold > rang || (currentTemperature - threshold < -rang && !isOnlyDownDirction)) {
flag = true;
}
}
三、单元测试
1、读取摄氏温度冰点,+/- 0.5°C 的波动仅通知一次
void readCelsiusTempTest1() {
vector<double>celsiusTemperature{ 1.5 ,1.0 ,0.5,0.0 ,-0.5 ,0.0 ,-0.5 ,0.0,0.5 ,0.0 };
gauge.readTemperature(celsiusTemperature, celsiusFreezingTemp, false, NO_TEMP_TRANSFORM);
}
输入数据:1.5 ,1.0 ,0.5,0.0 ,-0.5 ,0.0 ,-0.5 ,0.0,0.5 ,0.0
结果分析:输入数据包含多次+/- 0.5°C波动的数据,仅输出一次到达阈值通知
2、读取摄氏温度冰点,数据包含上升和下降方向,仅通知下降方向波动
void readCelsiusTempTest2() {
vector<double>celsiusTemperature{ 1.0 ,0.0 ,-0.1,0.0 };
gauge.readTemperature(celsiusTemperature, celsiusFreezingTemp, true, NO_TEMP_TRANSFORM);
}
输入数据:1.0 ,0.0 ,-0.1,0.0
结果分析:输入数据包含一次下降和一次上升数据,仅通知下降方向波动
3、读取摄氏温度沸点,+/- 0.5°C 的波动仅通知一次
void readCelsiusTempTest3() {
vector<double>celsiusTemperature{ 98.5 ,99.0 ,99.5,100.0 ,100.0 ,99.5 ,100.0 ,100.0,99.5 ,100.0 };
gauge.readTemperature(celsiusTemperature, celsiusBoilingTemp, false, NO_TEMP_TRANSFORM);
}
输入数据:98.5 ,99.0 ,99.5,100.0 ,100.0 ,99.5 ,100.0 ,100.0,99.5 ,100.0
结果分析:输入数据包含多次+/- 0.5°C波动的数据,仅输出一次到达阈值通知
4、转成华氏温度,温度数据、阈值按照摄氏温度输入的,由温度计内部接口计算转成华氏温度,波动范围也会相应取华氏温度的差值。
void readCelsiusTempTest4() {
vector<double>celsiusTemperature{ 1.5 ,1.0 ,0.5,0.0 ,-0.5 ,0.0 ,-0.5 ,0.0,0.5 ,0.0 };
gauge.readTemperature(celsiusTemperature, celsiusFreezingTemp, false, CELSIUS_TEMP_TO_FAHR);
}
输入数据:1.5 ,1.0 ,0.5,0.0 ,-0.5 ,0.0 ,-0.5 ,0.0,0.5 ,0.0
结果分析:输入数据包含多次+/- 0.5°C波动的数据,仅输出一次到达阈值通知
四、完整代码
1、TempertureGauge.h
#pragma once
#include
using namespace std;
enum TempeType
{
NO_TEMP_TRANSFORM = 0,
CELSIUS_TEMP_TO_FAHR = 1
};
class TemperatureGauge
{
public:
TemperatureGauge(bool flag = true);
~TemperatureGauge();
void readTemperature(vector<double> currentTemperature, double threshold,bool isOnlyDownDirction,TempeType type);
private:
void notifyAtThreshold(double currentTemperature, double threshold, bool isOnlyDownDirction,TempeType type);
bool flag;
};
2、TempertureGauge.cpp
#include "TempertureGauge.h"
#include
TemperatureGauge::TemperatureGauge(bool flag) : flag(flag)
{
}
TemperatureGauge::~TemperatureGauge()
{
}
void TemperatureGauge::readTemperature(vector<double> currentTemperature, double threshold, bool isOnlyDownDirction, TempeType type)
{
switch (type)
{
case NO_TEMP_TRANSFORM:
for (int i = 0; i < currentTemperature.size(); i++)
{
notifyAtThreshold(currentTemperature[i], threshold, isOnlyDownDirction, NO_TEMP_TRANSFORM);
}
break;
case CELSIUS_TEMP_TO_FAHR:
for (int i = 0; i < currentTemperature.size(); i++)
{
double fahr = currentTemperature[i] * 1.8 + 32;
double fahrThreshold = threshold * 1.8 + 32;
notifyAtThreshold(fahr, fahrThreshold, isOnlyDownDirction, CELSIUS_TEMP_TO_FAHR);
}
break;
default:
break;
}
}
void TemperatureGauge::notifyAtThreshold(double currentTemperature, double threshold, bool isOnlyDownDirction, TempeType type)
{
double rang = (type == CELSIUS_TEMP_TO_FAHR ? 0.9 : 0.5);
if (currentTemperature == threshold && flag)
{
cout << "Current temperature is reach threshold." << endl;
flag = false;
}
else if (currentTemperature - threshold > rang || (currentTemperature - threshold < -rang && !isOnlyDownDirction)) {
flag = true;
}
}
3、main.cpp
#include
#include
#include "TempertureGauge.h"
using namespace std;
TemperatureGauge gauge;
double celsiusFreezingTemp = 0; //摄氏温度冰点
double celsiusBoilingTemp = 100.0; //摄氏温度沸点
//读取摄氏温度冰点,+/- 0.5°C 的波动仅通知一次
void readCelsiusTempTest1() {
vector<double>celsiusTemperature{ 1.5 ,1.0 ,0.5,0.0 ,-0.5 ,0.0 ,-0.5 ,0.0,0.5 ,0.0 };
gauge.readTemperature(celsiusTemperature, celsiusFreezingTemp, false, NO_TEMP_TRANSFORM);
}
//读取摄氏温度冰点,数据包含上升和下降方向,仅通知下降方向波动
void readCelsiusTempTest2() {
vector<double>celsiusTemperature{ 1.0 ,0.0 ,-0.1,0.0 };
gauge.readTemperature(celsiusTemperature, celsiusFreezingTemp, true, NO_TEMP_TRANSFORM);
}
//读取摄氏温度沸点,+/- 0.5°C 的波动仅通知一次
void readCelsiusTempTest3() {
vector<double>celsiusTemperature{ 98.5 ,99.0 ,99.5,100.0 ,100.0 ,99.5 ,100.0 ,100.0,99.5 ,100.0 };
gauge.readTemperature(celsiusTemperature, celsiusBoilingTemp, false, NO_TEMP_TRANSFORM);
}
//转成华氏温度
void readCelsiusTempTest4() {
vector<double>celsiusTemperature{ 1.5 ,1.0 ,0.5,0.0 ,-0.5 ,0.0 ,-0.5 ,0.0,0.5 ,0.0 };
gauge.readTemperature(celsiusTemperature, celsiusFreezingTemp, false, CELSIUS_TEMP_TO_FAHR);
}
int main()
{
readCelsiusTempTest1();
//readCelsiusTempTest2();
//readCelsiusTempTest3();
//readCelsiusTempTest4();
return 0;
}