“在对象间定义一种一对多的依赖关系,以便当某对象的状态改变时,与它存在依赖关系的所有对象都能收到通知并自动进行更新。”
经典的就是解锁成就
void Physics::updateEntity(Entity& entity)
{
bool wasOnSurface = entity.isOnSurface();
entity.accelerate(GRAVITY);
entity.update();
if (wasOnSurface && !entity.isOnSurface())
{
notify(entity, EVENT_START_FALL);
}
}利用事件类型,通知到观察者。多个地方写通知事件就好了,不用没出都直接调用或硬编码一些内容。
接收事件的对象
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_;
};发出事件的对象
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...
};被观察者发出事件通知观察者
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里用指针数组来保存观察者,还可以用链表
class Subject
{
Subject()
: head_(NULL)
{}
// Methods...
private:
Observer* head_;
};class Observer
{
friend class Subject;
public:
Observer()
: next_(NULL)
{}
// Other stuff...
private:
Observer* next_;
};具体链表插入删除省略,遍历链表。
还可以用双向链表。
考虑到这一般都是极致优化才要做的,节点对象预分配,用对象池可以达到对象复用,加快内存分配和回收。