我正在尝试构建通用事件系统。代表和活动应该对彼此一无所知,而经理将处理一切。
考虑到这一点,我创建了一个由函数指针和模板化参数组成的模板化委托/侦听器。
class IDelegate
{
public:
IDelegate() {};
virtual ~IDelegate() = 0;
virtual void exec() = 0;
};
template<class Class, typename... Args>
class Delegate : public IDelegate
{
public:
typedef (Class::*Function)(Args);
Delegate(Class* inst, Function func) : instance(inst), function(func) {};
~Delegate() { instance = nullptr };
void exec(Args args)
{
instance->function(args);
}
private:
Class* instance;
Function function;
};
我在活动方面做了类似的事情。事件由一个ID和需要传递到函数指针的参数组成。
class IEvent
{
public:
IEvent() {};
virtual ~IEvent() = 0;
};
template<typename... Args>
class Event : IEvent
{
public:
Event(ID eventID, Args args) : id(eventID), arguments(args) {};
~Event() = default;
ID id;
Args arguments;
};
我选择使用模板,是希望不需要手动创建可能需要的每个事件/委托类。
最后我想做一个单身的经理人。
//EventHandler.h
#pragma once
#include <string>
#include <unordered_map>
#include <queue>
#include "Event.h"
typedef std::string ID;
typedef std::unordered_multimap<ID, void*> Listeners;
class EventHandler
{
public:
EventHandler(const EventHandler& copy) = delete;
~EventHandler();
EventHandler& operator= (const EventHandler& rhs) = delete;
void Initialize();
template<class Class, class TEvent>
void Run();
void Shutdown();
static Listeners::iterator& Register(ID id, IDelegate* listener);
static void Deregister(Listeners::iterator& iterator);
static void Post(IEvent* evnt);
private:
static Listeners listeners;
static std::queue<IEvent*> events;
static EventHandler* instance;
EventHandler() {};
EventHandler(const EventHandler& copy);
EventHandler& operator= (const EventHandler& rhs);
};
//EventHandler.cpp
#include "EventHandler.h"
EventHandler::~EventHandler()
{
instance = nullptr;
}
void EventHandler::Initialize()
{
instance = this;
}
void EventHandler::Run()
{
//TODO: Determine the Event and cast or instantiate to the right class
IEvent* evnt = events.front; //This should not be IEvent*, but Event<>*
events.pop();
listeners[evnt->id].exec(evnt->arguments); //The delegate may need to be casted too.
}
void EventHandler::Shutdown()
{
instance = nullptr;
}
Listeners::iterator& EventHandler::Register(ID id, IDelegate* listener)
{
Listeners::iterator iter = listeners.emplace(id, listener);
return iter;
}
void EventHandler::Deregister(Listeners::iterator& iterator)
{
listeners.erase(iterator);
}
void EventHandler::Post(IEvent* evnt)
{
events.emplace(evnt);
}
我遇到麻烦的地方是弄清楚我在Run()中实际使用了什么事件。如果可能的话,我想不用开关或类似的方法就可以避免使用模板化类。我曾经考虑过使函数指针具有相同的签名,因为这样做可以简化一些代码,但会使系统的灵活性降低。
谢谢您的帮助。