2 个不稳定版本
0.2.0 | 2023年6月19日 |
---|---|
0.1.0 | 2023年6月12日 |
695 在 游戏开发 中
每月80次下载
14KB
176 行
服务定位器模式 泛型实现
这是一个线程安全的泛型服务定位器实现,可以与任何特例对象一起使用。
描述
此模式用于提供对服务的全局访问,安全地,而不将服务与其使用的代码耦合。有关此模式的更多信息,请参阅 Robert Nyström 的书籍 Game Programming Patterns。
此模式的关键概念是
- 服务 - 定义服务(一个特质)的接口。
- 服务提供者 - 服务(实现特质)的实现。
- 服务定位器 - 定位服务提供者的对象。
用法
服务定位器是一个静态对象,可用于提供和请求服务。内部,它使用 RwLock
以确保线程安全。服务定位器是服务特质对象的泛型。
示例
use service_locator::ServiceLocator;
enum Sound {
Beep,
Laser,
}
// The service.
trait Audio {
fn play(&mut self, sound: Sound) {
// Some stuff.
}
fn stop(&mut self, sound: Sound) {
// Some stuff.
}
fn stop_all(&mut self) {
// Some stuff.
}
fn is_playing(&self, sound: Sound) -> bool {
false
}
}
// The service providers.
#[derive(Default)]
struct SDLAudio {
// Some stuff.
}
impl Audio for SDLAudio {
// Use the default implementation as it is an example.
}
#[derive(Default)]
struct OpenALAudio {
// Some stuff.
}
impl Audio for OpenALAudio {
// Use the default implementation as it is an example.
}
static AUDIO_SERVICE_LOCATOR: ServiceLocator<dyn Audio + Send + Sync> = ServiceLocator::new();
// The service is not provided yet.
assert!(AUDIO_SERVICE_LOCATOR.service().is_err());
// Provide the service.
AUDIO_SERVICE_LOCATOR.provide(Box::new(SDLAudio::default()));
// The service is now provided.
assert_eq!(AUDIO_SERVICE_LOCATOR.service().unwrap().is_playing(Sound::Beep), false);
// The service can be mutably borrowed.
let mut service = AUDIO_SERVICE_LOCATOR.service_mut().unwrap();
service.stop_all();
// IMPORTANT: Drop the service, as it's a guard, before to request it again to avoid a deadlock.
// Before we didn't drop the service because we didn't bind the service to a variable.
drop(service);
// Change the service provider.
AUDIO_SERVICE_LOCATOR.provide(Box::new(OpenALAudio::default()));
// The service is now from the new provider.
let is_playing_laser = AUDIO_SERVICE_LOCATOR.service()
// The closure is executed only if the service is provided,
// and ensures that the service is dropped after the closure execution.
.map(|service| service.is_playing(Sound::Laser))
.unwrap();
assert_eq!(is_playing_laser, false);
请记住处理错误,而不是使用 unwrap()
。它用于示例中,出于简单起见,因为它作为测试运行。
日志记录
该软件包使用 log
软件包进行日志记录。默认情况下禁用功能。
依赖项
~88KB