template <typename T>
class listener{
protected:
static TLSPtr<T> s_first; //为了线程安全
T *next;
protected:
void subscribe()
{
GEprintf("listener:%x\n",static_cast<T*>(this));
next = s_first;
s_first = static_cast<T*>(this);
}
void unsubscribe()
{
GEprintf("~listener:%x\n",static_cast<T*>(this));
T *temp = s_first;
if(temp == static_cast<T*>(this)){ //如果这是第一个节点。
s_first = next;
}else{
while(temp->next != static_cast<T*>(this));
temp->next = next;
}
}
listener()
{
subscribe();
}
~listener()
{
unsubscribe();
}
};
template <typename T>
TLSPtr<T> listener<T>::s_first;
观察者类继承listener类,并制定自身的类型,
这样一来,观察者对象自成链表。
发送消息的方法,见一个具体的观察者类:
class IMouseListener:public listener<IMouseListener>{
public:
static void send_down(int key,int x,int y)
{
IMouseListener *temp = s_first;
while(temp)
{
temp->mousedown(key,x,y);
temp = temp->next;
}
}
static void send_up(int key,int x,int y)
{
IMouseListener *temp = s_first;
while(temp)
{
temp->mouseup(key,x,y);
temp = temp->next;
}
}
static void send_move(int key,int x,int y)
{
IMouseListener *temp = s_first;
while(temp)
{
temp->mousemove(key,x,y);
temp = temp->next;
}
}
private:
//参数一: 表示该消息是鼠标上哪一个键发出的
virtual void mousedown(int key,int x,int y) = 0;
virtual void mouseup(int key,int x,int y) = 0;
virtual void mousemove(int key,int x,int y) = 0;
};
游戏中需要鼠标消息的类只要继承这个类就可以了。