各状態がイベントキューから取得したイベントを処理する状態パターンの実装があります。したがって、基本State
クラスには純粋仮想メソッドがありvoid handleEvent(const Event*)
ます。イベントは基本クラスを継承Event
しますが、各イベントには、異なるタイプ(int、stringなど)のデータが含まれています。イベントデータを抽出するにhandleEvent
は、受信したイベントのランタイムタイプを判別してから、ダウンキャストを実行する必要があります。イベントは動的に作成され、キューに保存されます(したがって、アップキャストはここで行われます...)。
ダウンキャストは悪い設計の兆候であることを私は知っていますが、この場合それを回避することは可能ですか?基本クラスのStateに各イベントの仮想ハンドラーが含まれるVisitorPatternを考えていますが、イベントをキューからデキューして現在の状態に渡すコードでダウンキャストを実行する必要があります。(少なくともこの場合、大きなswitch(eventID)
ものは1か所だけになります...)。ビジターパターンは、ダウンキャストを回避するための最良の方法(ベストプラクティス)ですか?
これが擬似コードです(boost::shared_ptr
この例ではパスしていますが、とにかくダウンキャストが発生します):
enum EventID
{
EVENT_1,
EVENT_2,
...
};
class Event
{
EventID id;
public:
Event(EventID id):id(id){}
EventID id() const {return id;}
virtual ~Event() = 0;
};
class Event1 : public Event
{
int n;
public:
Event1(int n):Event(EVENT_1), n(n){}
int getN() const {return n;}
};
class Event2 : public Event
{
std::string s;
public:
Event2(std::string s):Event(EVENT_2), s(s){}
std::string getS() const {return s;}
};
typedef boost::shared_ptr<Event> EventPtr;
class State
{
...
public:
...
virtual ~State() = 0;
virtual void handleEvent(const EventPtr& pEvent) = 0;
};
class StateA : public State
{
...
public:
void handleEvent(const EventPtr& pEvent)
{
switch(pEvent->id())
{
case EVENT_1:
int n = boost::static_pointer_cast<Event1>(pEvent)->getN();
...
break;
case EVENT_2:
std::string s = boost::static_pointer_cast<Event2>(pEvent)->getS();
...
break;
...
}
}
}