service locator
目录
简介
通常,service locator 与它们暴露的 service 紧密绑定。很难定义一个通用的解决方案。
这个小巧的类试图填补这一空白,并免除了为每个应用程序定义不同特定 locator 的负担。
Service locator
service locator 的 API 试图模仿 std::optional,并在其基础上增加了一些额外的功能,例如 allocator 支持。
有几个函数用于设置 service,即 emplace 和 allocate_emplace:
entt::locator<interface>::emplace<service>(argument);
entt::locator<interface>::allocate_emplace<service>(allocator, argument);
区别在于后者期望一个 allocator 作为第一个参数,并使用它来分配 service 本身。
一旦设置了 service,就可以使用 value 函数来检索它:
interface &service = entt::locator<interface>::value();
由于 service 可能未被设置(因此此函数可能导致未定义行为),还提供了 has_value 和 value_or 函数,用于测试 service locator 并在没有 service 时获取 fallback service:
if(entt::locator<interface>::has_value()) {
// ...
}
interface &service = entt::locator<interface>::value_or<fallback_impl>(argument);
所有参数仅在必要时使用,即如果 service 尚不存在,因此构造并返回 fallback service。在所有其他情况下,它们都会被丢弃。
最后,要重置 service,请使用 reset 函数。
Opaque handles
有时,将 service 的副本 转移 (transfer) 到另一个 locator 很有用。例如,在跨 boundaries 工作时,与动态加载的 module 共享 (share) service 是很常见的。
在这种情况下,选择并不多。其中之一是 导出 (export) service 并将其分配给不同 locator 的可能性。
这就是 handle 和 reset 函数的用途。
前者返回一个 opaque object,可用于 导出(或者更确切地说,获取其引用)service。后者还接受一个可选的 handle 参数,然后允许用户通过使用 opaque handle 初始化来重置 service:
auto handle = entt::locator<interface>::handle();
entt::locator<interface>::reset(handle);
值得注意的是,可以获取未初始化 service 的 handle 并将其与其他 locator 一起使用。当然,用户得到的结果只是在其他地方也拥有一个未初始化的 service。
请注意,导出 service 允许用户 共享 当前在 locator 中设置的对象。替换它不会替换该元素,即使某个 service 已使用指向前一个项目的 handle 进行了配置。
换句话说,如果将 audio service 替换为 null object 以使应用程序静音,并且原始 service 是共享的,则此操作不会传播到其他 locator。因此,共享原始 audio service 所有权的 module 仍然能够发出声音。