C++统一的自测接口实践
作者:IOT-Power
这篇文章主要介绍了C++统一的自测接口实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
可以,而且这是很常见的做法。关键不是让 CameraDevice 继承一个具体的 CameraSelfTest,而是让它继承一个统一的自测接口。
也就是:
CameraDevice 继承 ISelfTest ModbusDevice 继承 ISelfTest TcpDevice 继承 ISelfTest 然后统一放到 ISelfTest* 数组里遍历调用 SelfTest()
一、推荐结构
ISelfTest | |-- CameraDevice |-- ModbusDevice |-- TcpDevice |-- CanDevice
这样每个设备自己实现自己的自测逻辑,外部统一这样调用:
selfTests[i]->SelfTest();
二、完整 C++ 例子,不使用 std
#include <stdio.h>
#define SELF_TEST_OK 0
#define SELF_TEST_FAILED 1
// =====================================================
// 1. 自测接口
// =====================================================
class ISelfTest
{
public:
virtual ~ISelfTest()
{
}
virtual int SelfTest() = 0;
virtual const char* GetSelfTestName() = 0;
};
// =====================================================
// 2. 摄像头设备
// CameraDevice 本身具备自测能力
// =====================================================
class CameraDevice : public ISelfTest
{
public:
void Start()
{
printf("CameraDevice Start\n");
}
void Stop()
{
printf("CameraDevice Stop\n");
}
int CheckImage()
{
printf("CameraDevice Check Image\n");
return 1;
}
int CheckFrameRate()
{
printf("CameraDevice Check Frame Rate\n");
return 1;
}
const char* GetSelfTestName()
{
return "CameraDevice SelfTest";
}
int SelfTest()
{
printf("========== CameraDevice SelfTest Start ==========\n");
Start();
if (CheckImage() == 0)
{
printf("CameraDevice SelfTest Failed: Image Error\n");
Stop();
return SELF_TEST_FAILED;
}
if (CheckFrameRate() == 0)
{
printf("CameraDevice SelfTest Failed: FrameRate Error\n");
Stop();
return SELF_TEST_FAILED;
}
Stop();
printf("CameraDevice SelfTest OK\n");
return SELF_TEST_OK;
}
};
// =====================================================
// 3. Modbus设备
// ModbusDevice 本身也具备自测能力
// =====================================================
class ModbusDevice : public ISelfTest
{
public:
void Open()
{
printf("ModbusDevice Open Serial Port\n");
}
void Close()
{
printf("ModbusDevice Close Serial Port\n");
}
int CheckConnection()
{
printf("ModbusDevice Check Connection\n");
return 1;
}
int CheckRegister()
{
printf("ModbusDevice Check Register\n");
return 1;
}
const char* GetSelfTestName()
{
return "ModbusDevice SelfTest";
}
int SelfTest()
{
printf("========== ModbusDevice SelfTest Start ==========\n");
Open();
if (CheckConnection() == 0)
{
printf("ModbusDevice SelfTest Failed: Connection Error\n");
Close();
return SELF_TEST_FAILED;
}
if (CheckRegister() == 0)
{
printf("ModbusDevice SelfTest Failed: Register Error\n");
Close();
return SELF_TEST_FAILED;
}
Close();
printf("ModbusDevice SelfTest OK\n");
return SELF_TEST_OK;
}
};
// =====================================================
// 4. 统一遍历执行自测
// =====================================================
void RunAllSelfTest(ISelfTest* selfTests[], int count)
{
int i = 0;
for (i = 0; i < count; i++)
{
if (selfTests[i] == NULL)
{
continue;
}
printf("\nRun %s\n", selfTests[i]->GetSelfTestName());
int result = selfTests[i]->SelfTest();
if (result == SELF_TEST_OK)
{
printf("Final Result: OK\n");
}
else
{
printf("Final Result: FAILED\n");
}
}
}
// =====================================================
// 5. main 测试
// =====================================================
int main()
{
CameraDevice camera;
ModbusDevice modbus;
ISelfTest* selfTests[10];
int count = 0;
selfTests[count++] = &camera;
selfTests[count++] = &modbus;
RunAllSelfTest(selfTests, count);
return 0;
}
三、重点理解这句
ISelfTest* selfTests[10];
这个数组里面放的不是具体设备类型,而是统一的自测接口指针。
所以你可以放:
selfTests[count++] = &camera; selfTests[count++] = &modbus;
虽然 camera 是:
CameraDevice camera;
modbus 是:
ModbusDevice modbus;
但它们都继承了:
ISelfTest
所以都可以被当成:
ISelfTest*
来统一管理。
四、这种方式叫什么?
这个核心是:
接口 + 多态
不是工厂模式。
外部统一调用:
selfTests[i]->SelfTest();
但是实际执行的是:
CameraDevice::SelfTest() ModbusDevice::SelfTest()
这就是 C++ 的虚函数多态。
五、你不要这样设计
不建议这样:
class CameraDevice : public CameraSelfTest
{
};
因为这样会变成:
设备继承具体自测类
逻辑会比较别扭。
更合理的是:
class CameraDevice : public ISelfTest
{
public:
int SelfTest();
};
也就是:
设备继承自测接口 设备自己实现自己的自测逻辑
六、如果你的设备本来已经有父类怎么办?
比如你原来已经有:
class CDevice
{
public:
virtual void Start() = 0;
virtual void Stop() = 0;
};
那也可以这样:
class CameraDevice : public CDevice, public ISelfTest
{
public:
void Start();
void Stop();
int SelfTest();
const char* GetSelfTestName();
};
这是多继承,但这里继承的是接口类,问题不大。
七、什么时候适合这样做?
适合你的情况:
10 种设备都需要自测 自测就是设备自身能力的一部分 希望后面可以统一遍历调用
最终用法就是:
ISelfTest* selfTests[10]; selfTests[0] = &camera; selfTests[1] = &modbus; selfTests[2] = &tcp; selfTests[3] = &can; RunAllSelfTest(selfTests, 4);
这个结构很清楚。设备自己负责自己的自测,外部只负责统一调度。
八、总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
