16_游戏编程模式ServiceLocator 服务定位
####简单说,就是某个系统作为一个服务,对全局系统可见. Service Locator (服务定位) ```
//简单粗暴的代码, 使用声音系统 // Use a static class?
AudioSystem::playSound(VERY_LOUD_BANG); // Or maybe a singleton?
AudioSystem::instance()->playSound(VERY_LOUD_BANG);
``` 类比:
如果我换了电话号码,需要通知我所有联系人,我换了电话号码
如果有一个提供个人信息的服务, 我只需要更新我的个人信息, 别人就可以查到我最新的电话号码 ### 模式定义
service类定义了抽象的操作借口, 一个具体的服务提供者实现这些接口.
service locator 找到合适的服务提供者,并且隐藏服务者具体类型和查找过程. ### 何时使用
某段程序 需要在任何时候,任何地方进行访问, 这样会带来麻烦,
比如说单例模式, 服务定位也有同样的问题. 尽量少的使用! 带来灵活性的同时,性能会下降. ### 注意事项
保证服务能被定位到
定位是全局访问的. 但有些服务在某些特定场景下才能正常使用. ### Sample Code
``` // Service
class Audio
{
public:
virtual ~Audio() {}
virtual void playSound(int soundID) = ;
virtual void stopSound(int soundID) = ;
virtual void stopAllSounds() = ;
}; // Service Provider class ConsoleAudio : public Audio {} // Locator
class Locator
{
public:
static Audio* getAudio() { return service_; } static void provide(Audio* service)
{
service_ = service;
} private:
static Audio* service_;
}; //游戏启动时
Audio *audio = Locator::getAudio();
audio->playSound(VERY_LOUD_BANG); //使用定位
Audio *audio = Locator::getAudio();
audio->playSound(VERY_LOUD_BANG); // 当所使用定位的时候, 服务提供还没有设置, 将会出错, 所谓我们提供一个默认的服务 class NullAudio: public Audio
{
public:
virtual void playSound(int soundID) { /* Do nothing. */ }
virtual void stopSound(int soundID) { /* Do nothing. */ }
virtual void stopAllSounds() { /* Do nothing. */ }
}; class Locator
{
public:
static void initialize() { service_ = &nullService_; } static Audio& getAudio() { return *service_; } static void provide(Audio* service)
{
if (service == NULL)
{
// Revert to null service.
service_ = &nullService_;
}
else
{
service_ = service;
}
} private:
static Audio* service_;
static NullAudio nullService_;
}; ``` ### 装饰器模式 ```
\\ 声音执行的log类 class LoggedAudio : public Audio
{
public:
LoggedAudio(Audio &wrapped)
: wrapped_(wrapped)
{} virtual void playSound(int soundID)
{
log("play sound");
wrapped_.playSound(soundID);
} virtual void stopSound(int soundID)
{
log("stop sound");
wrapped_.stopSound(soundID);
} virtual void stopAllSounds()
{
log("stop all sounds");
wrapped_.stopAllSounds();
} private:
void log(const char* message)
{
// Code to log message...
} Audio &wrapped_;
}; // 把服务提供者换成装饰之后的类
void enableAudioLogging()
{
// Decorate the existing service.
Audio *service = new LoggedAudio(Locator::getAudio()); // Swap it in.
Locator::provide(service);
}
``` ### 设计判断 #### 服务如何定位 ```
外部代码注册
. 快速简单
. 我们控制提供者的构建
. 可以在运行时改变服务
. 定位依赖于外部代码
编译期绑定
. 快速
. 保证服务可用
. 不能很容易的改变服务
运行时配置
. 改变服务不用重新编译
. 不用程序来修改服务(让策划配置)
. 可以提同时提供多个服务(不同的配置)
. 复杂
. 加载服务耗时(解析配置,等等)
``` #### 服务不能被定位到的时候
```
让用户处理
. 用户决定怎么面对错误
. 服务的用户必须处理错误
关闭游戏
. 用户不必处理丢失服务
. 如果服务找不到,就关闭游戏(容易debug, 但是会让使用这个服务的同事头疼)
返回一个null服务(默认服务)
. 用户不必处理丢失服务
. 游戏会继续运行,即使服务丢失(debug困难)
``` #### 服务的作用域
```
全局访问
. 服务提供者可控制, 禁止到处实例服务提供者
. 在哪使用和何时使用服务, 我们无法控制
受限访问
. 控制耦合, 把服务控制在一个继承树里, 系统里不耦合的部分还保持不耦合
. 导致重复. 比如不同的类都要保存一个服务类的引用. 恰当的设置服务的作用域, 比如说网络服务限制在online class里面访问, 而log系统则是全局的.
``` ## see also
服务定位类似于单例, 根据需要不同选用合适的设计
unity 融合了服务定位与组件模式, GetComponent可以当作获取服务.
XNA 框架 Game 类的实例有一个GameServices对象, 可以用来注册, 定位任何类型的服务
16_游戏编程模式ServiceLocator 服务定位的更多相关文章
- 游戏编程模式KeyNote
[游戏编程模式KeyNote] 1.命令模式. 重做在游戏中并不常见,但重放常见.一种简单的重放实现是记录游戏每帧的状态,这样它可以回放,但那会消耗太多的内存.相反,很多游戏记录每个实体每帧运行的命令 ...
- 游戏编程模式 Game Programming Patterns (Robert Nystrom 著)
第1篇 概述 第1章 架构,性能和游戏 (已看) 第2篇 再探设计模式 第2章 命令模式 (已看) 第3章 享元模式 (已看) 第4章 观察者模式 (已看) 第5章 原型模式 (已看) 第6章 单例模 ...
- 15_游戏编程模式EventQueue
#### 两个例子 .GUI event loop ``` while (running) { // 从事件队列里获取一个事件 Event event = getNextEvent(); // Han ...
- 游戏编程算法与技巧 Game Programming Algorithms and Techniques (Sanjay Madhav 著)
http://gamealgorithms.net 第1章 游戏编程概述 (已看) 第2章 2D图形 (已看) 第3章 游戏中的线性代数 (已看) 第4章 3D图形 (已看) 第5章 游戏输入 (已看 ...
- DirectX游戏编程入门
刚开始学习D3D,安装完DirectX9后,在VS2008中新建Win32项目· ----------------------------------------------------------- ...
- 为了支持AOP的编程模式,我为.NET Core写了一个轻量级的Interception框架[开源]
ASP.NET Core具有一个以ServiceCollection和ServiceProvider为核心的依赖注入框架,虽然这只是一个很轻量级的框架,但是在大部分情况下能够满足我们的需要.不过我觉得 ...
- PHP中应用Service Locator服务定位及单例模式
单例模式将一个对象实例化后,放在静态变量中,供程序调用. 服务定位(ServiceLocator)就是对象工场Factory,调用者对象直接调用Service Locator,与被调用对象减轻了依赖关 ...
- Windows游戏编程之从零开始d
Windows游戏编程之从零开始d I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来 ...
- DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
随机推荐
- microsoft cl.exe 编译器
cl.exe是visual stdio 内置的编译器,visual stdio包含各种功能,有些功能可能这辈子都用不到,体积庞大,如果是 开发比较大或者有图形的项目,vs是首选.更多情况时更喜欢使用文 ...
- 解决问题知识点--mysql数据库
一: 连接 多表的字段中含null的 多表查询 ----左右连接查询! 例: 一张 emp(emano,ename,sal,deptno) 雇员表, 一张 dept(deptno,dname) 部 ...
- 42和为S的两个数字
题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. 设置 ...
- iOS NSCoding 的学习 和 使用
起初接触的轻量级 物理存储 方式 是 plist 可以存储 系统级别的 字典 数组 但是不能存储自定义的对象类 那会 用自定义对象做存储的 需求也不大 主要 是 还没建立面向对象意识,会的也少. ...
- excel中如何取消自动超链接?
最近做的表格有点多,年终述职也到了.总有一些地方生疏了,幸好还有点小印象.记录下来,以后可以回来看看. 方法一 适合单个链接的取消 1 输入网址后,按回车键确认,快捷键ctrl+z,即可取消,这种不好 ...
- 摊铺机基本参数介绍(鼎盛天工WTD9501A)
柴油水冷发动机,马力强劲,功率储备系数大,低噪音.低污染,经济性好,低温起动性能好.微电子控制,分别实现刮板输送.螺旋供料左右独立驱动,可实现自动供料,保持熨平板前物料均匀,调平系统响应速度快,调平精 ...
- iOS_核心动画(二)
目 录: 一.Core Animation开发步骤 二.Core Animation的继承结构 三.CAAnimation常用的属性 四.CAPropertyAnimation(属性动画) 五.CAB ...
- log4j2.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!--日志级别以及优先级排序: OFF > FATAL ...
- springmvc 学习笔记1
1.新建JAVAWEB程序,并导入jar包到工程.(IOC,SPRING MVC两部分) a.复制JAR包到lib文件夹下. b.选上所有jar包,右键后选"Bulid Path" ...
- js实现级联菜单(没有后台)
html代码: <!-- js级联菜单 --> <div id="cascMenu"> <select id="select" o ...