私は、ユーザーが設定を変更してから情報をストリーミングすることにより、ハードウェアのビットと対話できるようにするツールを書いています。
これを行うために、いくつかのスレッドを実行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ステートメントと基本クラスのある種の列挙されたメッセージタイプ識別子なしでそれを行うことができる唯一の方法です。