Event Queue 设计模式
意图:旨在解耦生产者与消费者
动机:
生活在互联网环境之下,我们一般都听说过"事件队列",也可以叫做"消息队列"等等.为了刷新你的认知,我们一起看一些这个设计模式的一些表征.循环事件
当我们进行用户接口开发的时候,我们将会面对用户事件.每次用户点击我们做的软件上边的一个按钮,或者一个菜单等等,软件系统都会产生一个事件,并且把这个事件扔给我们的软件系统进行处理.而我们的工作就是catch这个事件,并进行处理.
为了接收消息,你在处理的过程中有可能需要的是一个循环体:
while (running)
{
Event event = getNextEvent();
// Handle event...
}
通过对getNextEvent()方法的调用,你将获取一个未处理的事件,并可以加上你对这个事件的处理方式.
但是问题来了,一系列事件推送过来时,怎么能保证事件不会被丢失,getNextEvent()这个方法是从什么地方获取这些已经推送过来的事件呢?
- 事件中心
大部分的游戏系统都不是事件驱动类型的,但是他们的中心系统一般都会有自己的事件队列.而事件队列一般都是用来保证系统之间的解耦. - Demo
创建一个可以播放声音的类,主要用来去加载适当的音频资源,并且找到对应的播放频道,最后进行播放.
class Audio
{
public:
static void playSound(SoundId id, int volume);
};
接着我们再来创建这个方法具体的实现:
void Audio::playSound(SoundId id, int volume)
{
ResourceId resource = loadSound(id);
int channel = findOpenChannel();
if (channel == -1) return;
startSound(resource, channel, volume);
}
最后来创建调度这个方法的菜单:
class Menu
{
public:
void onSelect(int index)
{
Audio::playSound(SOUND_BLOOP, VOL_MAX);
// Other stuff...
}
};
完成上述内容之后,我们会发现当我们切换菜单的时候,有的一些 画面将会卡住,那么问题来了:
- 在音频设备进行播放的时间,接口将会阻塞用户的调用.
因为我们的playSound()方式是同步的----所以知道播放设备播放完成之后,才会进行响应.