我正在編寫一個工具,通過更改設置,然後流式傳輸信息,使用戶能夠與一些硬件進行交互。如何在通過隊列傳遞信息時避免向下轉換?
要做到這一點,我有幾個線程運行:EquipmentInterface
和DataProcessor
它們通過Queue
連接。
的EquipmentInterface
螺紋具有的方法來改變所述設備(Rotate
和Refocus
例如),並將所得的信息(CurrentAngle
和CurrentFocalDistance
)被添加到Queue
上設置。一旦設置正確,有方法StartStreaming
和StopStreaming
,並且一旦流式傳輸開始,將來自設備的數據打包並添加到隊列中。
放置在隊列中的所有信息都來自單個BaseMessage
類,其中包含消息類型的指示。然後,我得到了角度,焦距,開始和結束流式以及數據本身的消息類型。
DataProcessor
監聽隊列的另一端,並根據當前角度/焦距,處理後續數據。
現在,事情是,我在數據處理器中有一個函數,它使用switch語句對進入的消息進行類型檢查。然後這些消息被下載到合適的類型並傳遞給適當的處理程序。實際上,除了一個DataProcessor監聽單個隊列外,實際上還有多個隊列中的多個監聽器(一些存儲到磁盤,一些顯示Gui上的信息)。每次添加一些信息時,我必須創建一個新的BaseMessage
派生類,向該基類添加一個新類型,然後更新每個使用者中的switch語句以應對新消息。
關於這個架構的一些事情對我來說感覺不對,而且我最近一直在閱讀很多關於下載的內容。從我所看到的情況來看,普遍的共識似乎是what I'm doing is a bad code smell。我見過a suggestion which use Boost,但他們看起來沒有比我更清楚的switch語句(也許我錯過了什麼?)。
所以我的問題是:我應該試圖避免switch-statement/downcasting解決方案,如果是這樣,如何?
我的實現是在C++/CLI中,因此.net或C++解決方案就是我所追求的。
編輯研究 - 基於iammilind和stfaanv的意見,這是諸如此類的事情,你是在暗示:
class QueuedItem
{
public:
QueuedItem() { }
virtual ~QueuedItem() { }
};
class Angle : public QueuedItem
{
public:
Angle() {}
virtual ~Angle() { }
};
class FocalLength : public QueuedItem
{
public:
FocalLength() {}
virtual ~FocalLength() { }
private:
};
class EquipmentHandler
{
protected:
virtual void ProcessAngle(Angle* angle) {};
virtual void ProcessFocalLength(FocalLength* focalLength) {};
public:
void ProcessMessages(QueuedItem* item)
{
Angle* pAngle = dynamic_cast<Angle*>(item);
if(pAngle != NULL)
{
ProcessAngle(pAngle);
}
FocalLength* pFocalLength = dynamic_cast<FocalLength*>(item);
if(pFocalLength != NULL)
{
ProcessFocalLength(pFocalLength);
}
}
};
class MyDataProcessor : public EquipmentHandler
{
protected:
virtual void ProcessAngle(Angle* angle) override { printf("Processing Angle"); }
virtual void ProcessFocalLength(FocalLength* focalLength) override { printf("Processing FocalLength"); };
};
int _tmain(int argc, _TCHAR* argv[])
{
// Equipment interface thread...
FocalLength* f = new FocalLength();
QueuedItem* item = f; // This gets stuck onto the queue
// ...DataProcessor thread (after dequeuing)
QueuedItem* dequeuedItem = item;
// Example of a DataProcessor implementation.
// In reality, this would
MyDataProcessor dataProc;
dataProc.ProcessMessages(dequeuedItem);
return 0;
}
...並可以將其簡化? ProcessMessages
感覺有點笨重,但這是我能夠看到的,在基類中沒有switch語句和某種枚舉消息類型標識符的唯一方法。
看起來你正迫切需要* Dynamic Polymorphism和Dynamic dispatch *。 – 2012-04-11 07:12:05
爲什麼不在聲明基類中的'virtual'函數並在其所有子項中實現? – iammilind 2012-04-11 07:13:12
@iammilind:這肯定會節省多次重新實現switch語句,但並沒有完全擺脫它。這是確定要調用哪個處理程序的最有效方法嗎? – 2012-04-11 07:24:06