C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++统一的自测接口

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);

这个结构很清楚。设备自己负责自己的自测,外部只负责统一调度。

八、总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文