我正在编写一个工具,它使用户能够通过更改设置然后流式传输信息来与一些硬件进行交互。
为此,我运行了几个线程:EquipmentInterface
它们DataProcessor
通过Queue
.
该EquipmentInterface
线程具有更改设备设置的方法(例如),并将结果信息(和Rotate
)添加到. 一旦设置正确,就会有方法,一旦开始流式传输,来自设备的数据就会被打包并添加到队列中。Refocus
CurrentAngle
CurrentFocalDistance
Queue
StartStreaming
StopStreaming
放置在队列上的所有信息都来自一个BaseMessage
包含消息类型指示的类。然后,我导出了角度、焦距、开始和结束流媒体的消息类型,当然还有数据本身。
监听队列的DataProcessor
另一端并根据当前角度/焦距处理后续数据。
现在,问题是,我在数据处理器中有一个函数,它使用 switch 语句对传入的消息进行类型检查。然后将这些消息向下转换为适当的类型并传递给适当的处理程序。实际上,不只是一个 DataProcessor 监听一个队列,而是多个队列上的多个监听器(一些存储到磁盘,一些在 gui 上显示信息)。每次我添加一些信息时,我都必须创建一个新的BaseMessage
派生类,向该基类添加一个新类型,然后更新每个消费者中的 switch 语句以处理新消息。
这种架构的某些东西让我觉得不对劲,最近我读了很多关于向下转换的文章。从我所见,普遍的共识似乎是我正在做的是一种糟糕的代码气味。我看到了一个使用 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 语句和基类中的某种枚举消息类型标识符。