我正在设计一个观察者模式,它应该以这种方式工作:观察者调用AddEventListener
的{{1}}方法并传递一个字符串,该字符串是EventDispatcher
的名称, PointerToItself 和 PointerToItsMemberMethod
在event
内发生event
之后;它会查看订阅列表,如果有一些订阅,则分配给此事件会调用EventDispatcher
的{{1}}方法。
我来到这个action
。 注意包含一些伪代码。
这是两个问题:
observer
?EventDispatcher.h
的类型
PS :不,我不会使用action
或任何其他库。
struct Subscription
此标头在boost
#pragma once
#include <vector>
#include <string>
using namespace std;
struct Subscription
{
void* observer;
string event;
/* u_u */ action;
};
class EventDispatcher
{
private:
vector<Subscription> subscriptions;
protected:
void DispatchEvent ( string event );
public:
void AddEventListener ( Observer* observer , string event , /* u_u */ action );
void RemoveEventListener ( Observer* observer , string event , /* u_u */ action );
};
答案 0 :(得分:3)
您可以定义Action类或传递lambda函数(C ++ 11)。在后一种情况下,行动可以定义为
function<void (EventDispatcher*)> action;
您将按如下方式注册观察者
Observer * me = this;
observable->AddEventListener (this, "EventName", [me] (EventDispatcher* dispatcher) {
// code here; me is available
});
您应该使用智能弱指针将Observers存储在EventDispatcher中,这样您就不必关心取消注册了。
编辑:添加了以下示例(可能只有一个订阅,但应说明这个想法 - 您必须小心不要引用不再存在的对象)
struct Observable {
std::weak_ptr<function<void (const Observable&)>> action;
void AddEventListener (std::weak_ptr<function<void (const Observable&)>> theAction) {
action = theAction;
}
void EventRaised () {
if (!action.expired ()) {
auto theAction = action.lock ();
(*theAction) (*this);
}
}
};
struct Observer {
...
void CallOnEvent (const Observable & observable) {
// do something
}
// field to store the action as long as it is needed
std::shared_ptr<function<void (const Observable&)>> action;
void ... {
auto me = this;
action = std::make_shared<function<void (const Observable&)>> (
[me] (const Observable& observable) {
me->CallOnEvent (observable);
}
);
// we could have as well used std::bind
observable.AddEventListener (action);
}
};
答案 1 :(得分:1)
在最简单的形式中,u_u可以是一个函数指针,例如
typedef void (*u_u)(void*); // or whatever arguments u like
然后你只提供一个在触发事件时调用的函数。
void myaction(void* arg)
{
...
}
Subscription s;
...
s.action = myaction;
答案 2 :(得分:1)
也许您应该创建一个由“用户”派生的类:
class Action {
public:
friend class EventDispatcher;
virtual SomeResultType DoThis() = 0;
private:
/* Some common data */
};
只需将一些派生类的Action类型变量传递给AddEventListener。触发相应的事件时,只需填写公共数据并调用DoThis()方法。
void EventDispatcher::DispatchEvent ( string event )
{
int key = 0;
while ( key < this->subscriptions.size() )
{
Subscription subscription = this->subscriptions[key];
if ( subscription.event == event )
{
subscription->action();
};
};
};
对于AddEventListener:
void EventDispatcher::AddEventListener ( Observer* observer , string event , Action* action )
{
Subscription subscription = { observer , event , action );
this->subscriptions.push_back ( subscription );
};
Action派生类的一个示例:
class myAction: public Action {
public:
// Implement the DoThis() method
void SomeResultType DoThis() {
cout << "Hello World!";
return SomeValue;
}
};
// To use the action,
myAction* act = new myAction;
myEventDispatcher.AddEventListener(someObserver, "HelloWorld", act);
这是实施操作(和回调)的最安全的方法之一。