# 游戏中的观察者模式

“在对象间定义一种一对多的依赖关系，以便当某对象的状态改变时，与它存在依赖关系的所有对象都能收到通知并自动进行更新。”

经典的就是解锁成就

```cpp
void Physics::updateEntity(Entity& entity) 
{
　bool wasOnSurface = entity.isOnSurface();
　entity.accelerate(GRAVITY);
　entity.update();
　if (wasOnSurface && !entity.isOnSurface())
　{
　　notify(entity, EVENT_START_FALL);
　}
}
```

利用事件类型，通知到观察者。多个地方写通知事件就好了，不用没出都直接调用或硬编码一些内容。

## 观察者

接收事件的对象

```cpp
class Observer
{
public: 
　virtual ~Observer() {}
　virtual void onNotify(const Entity& entity,   
　　　　　　　　　　　　　　　　　Event event) = 0; 
};

class Achievements : public Observer
{
public:
　virtual void onNotify(const Entity& entity,
　　　　　　　　　　　　　　Event event)
　{
　　switch (event)
　　{
　　case EVENT_ENTITY_FELL:
　　　if (entity.isHero() && heroIsOnBridge_)
　　　{
　　　　unlock(ACHIEVEMENT_FELL_OFF_BRIDGE);
　　　}
　　　break;

　　　//Handle other events...


　　　// Update heroIsOnBridge_...


　　}
　}

private:
　void unlock(Achievement achievement)
　{
  // Unlock if not already unlocked...


　}

　bool heroIsOnBridge_;
};
```

## 被观察者

发出事件的对象

```cpp
class Subject
{
private: 
　Observer* observers_[MAX_OBSERVERS]; 
　int numObservers_;
};

class Subject
{
public:
　void addObserver(Observer* observer)
　{
    //Add to array...
　}

　void removeObserver(Observer* observer)
　{
   //Remove from array..
　}

   //Other stuff...

};
```

被观察者发出事件通知观察者

```cpp
class Subject
{
protected:
　void notify(const Entity& entity, Event event)
　{
　　for (int i = 0; i < numObservers_; i++)
　　{
　　　observers_[i]->onNotify(entity, event);
　　}
　}
　// Other stuff...


};
```

## 链式观察者

上面Subject里用指针数组来保存观察者，还可以用链表

```cpp
class Subject
{
　Subject()
　: head_(NULL)
　{}

　// Methods...


private:
　Observer* head_;
};
```

```cpp
class Observer
{
　friend class Subject;

public:
　Observer()
　: next_(NULL)
　{}

　// Other stuff...


private:
　Observer* next_;
};
```

具体链表插入删除省略，遍历链表。

还可以用双向链表。

## 链表节点池

考虑到这一般都是极致优化才要做的，节点对象预分配，用对象池可以达到对象复用，加快内存分配和回收。
