C++統(tǒng)一的自測(cè)接口實(shí)踐
可以,而且這是很常見(jiàn)的做法。關(guān)鍵不是讓 CameraDevice 繼承一個(gè)具體的 CameraSelfTest,而是讓它繼承一個(gè)統(tǒng)一的自測(cè)接口。
也就是:
CameraDevice 繼承 ISelfTest ModbusDevice 繼承 ISelfTest TcpDevice 繼承 ISelfTest 然后統(tǒng)一放到 ISelfTest* 數(shù)組里遍歷調(diào)用 SelfTest()
一、推薦結(jié)構(gòu)
ISelfTest | |-- CameraDevice |-- ModbusDevice |-- TcpDevice |-- CanDevice
這樣每個(gè)設(shè)備自己實(shí)現(xiàn)自己的自測(cè)邏輯,外部統(tǒng)一這樣調(diào)用:
selfTests[i]->SelfTest();
二、完整 C++ 例子,不使用 std
#include <stdio.h>
#define SELF_TEST_OK 0
#define SELF_TEST_FAILED 1
// =====================================================
// 1. 自測(cè)接口
// =====================================================
class ISelfTest
{
public:
virtual ~ISelfTest()
{
}
virtual int SelfTest() = 0;
virtual const char* GetSelfTestName() = 0;
};
// =====================================================
// 2. 攝像頭設(shè)備
// CameraDevice 本身具備自測(cè)能力
// =====================================================
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設(shè)備
// ModbusDevice 本身也具備自測(cè)能力
// =====================================================
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. 統(tǒng)一遍歷執(zhí)行自測(cè)
// =====================================================
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 測(cè)試
// =====================================================
int main()
{
CameraDevice camera;
ModbusDevice modbus;
ISelfTest* selfTests[10];
int count = 0;
selfTests[count++] = &camera;
selfTests[count++] = &modbus;
RunAllSelfTest(selfTests, count);
return 0;
}
三、重點(diǎn)理解這句
ISelfTest* selfTests[10];
這個(gè)數(shù)組里面放的不是具體設(shè)備類(lèi)型,而是統(tǒng)一的自測(cè)接口指針。
所以你可以放:
selfTests[count++] = &camera; selfTests[count++] = &modbus;
雖然 camera 是:
CameraDevice camera;
modbus 是:
ModbusDevice modbus;
但它們都繼承了:
ISelfTest
所以都可以被當(dāng)成:
ISelfTest*
來(lái)統(tǒng)一管理。
四、這種方式叫什么?
這個(gè)核心是:
接口 + 多態(tài)
不是工廠模式。
外部統(tǒng)一調(diào)用:
selfTests[i]->SelfTest();
但是實(shí)際執(zhí)行的是:
CameraDevice::SelfTest() ModbusDevice::SelfTest()
這就是 C++ 的虛函數(shù)多態(tài)。
五、你不要這樣設(shè)計(jì)
不建議這樣:
class CameraDevice : public CameraSelfTest
{
};
因?yàn)檫@樣會(huì)變成:
設(shè)備繼承具體自測(cè)類(lèi)
邏輯會(huì)比較別扭。
更合理的是:
class CameraDevice : public ISelfTest
{
public:
int SelfTest();
};
也就是:
設(shè)備繼承自測(cè)接口 設(shè)備自己實(shí)現(xiàn)自己的自測(cè)邏輯
六、如果你的設(shè)備本來(lái)已經(jīng)有父類(lèi)怎么辦?
比如你原來(lái)已經(jīng)有:
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();
};
這是多繼承,但這里繼承的是接口類(lèi),問(wèn)題不大。
七、什么時(shí)候適合這樣做?
適合你的情況:
10 種設(shè)備都需要自測(cè) 自測(cè)就是設(shè)備自身能力的一部分 希望后面可以統(tǒng)一遍歷調(diào)用
最終用法就是:
ISelfTest* selfTests[10]; selfTests[0] = &camera; selfTests[1] = &modbus; selfTests[2] = &tcp; selfTests[3] = &can; RunAllSelfTest(selfTests, 4);
這個(gè)結(jié)構(gòu)很清楚。設(shè)備自己負(fù)責(zé)自己的自測(cè),外部只負(fù)責(zé)統(tǒng)一調(diào)度。
八、總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C/C++惡意代碼盤(pán)點(diǎn)之文件自動(dòng)刪除
惡意代碼的分類(lèi)包括計(jì)算機(jī)病毒、蠕蟲(chóng)、木馬等,有些技術(shù)經(jīng)常用到,有的也是必然用到。今天我們就分享一下文件自動(dòng)刪除,感興趣的可以了解一下2022-09-09
C語(yǔ)言 動(dòng)態(tài)內(nèi)存分配的詳解及實(shí)例
這篇文章主要介紹了C語(yǔ)言 動(dòng)態(tài)內(nèi)存分配的詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2016-09-09

