Как не унывать?

У меня есть реализация шаблона состояний, где каждое состояние обрабатывает события, которые оно получает из очереди событий. Таким образом, базовый класс Stateимеет чисто виртуальный метод void handleEvent(const Event*). События наследуют базовый класс Event, но каждое событие содержит свои данные, которые могут быть другого типа (например, int, string... или что-то еще). handleEventдолжен определить тип времени выполнения полученного события, а затем выполнить приведение вниздля извлечения данных события. События создаются динамически и сохраняются в очереди (поэтому здесь происходит восходящее преобразование...).

Я знаю, что понижение приведения является признаком плохого дизайна, но можно ли его избежать в данном случае?Я имею в виду Шаблон посетителя, где базовый класс State будет содержать виртуальный обработчики для каждого события, но затем снова должно быть выполнено понижение в части кода, которая удаляет событие из очереди и передает его в текущее состояние. (По крайней мере, в этом случае большой переключатель (eventID)будет только в одном месте...).Является ли Шаблон посетителя лучшим способом (передовой практикой) избежать понижения рейтинга?

Вот псевдокод (в этом примере я передаю 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;
         ... 

      }
   }   
}
7
задан Dave Schweisguth 13 February 2016 в 23:15
поделиться