第1篇 概述
第1章 架构,性能和游戏 (已看)
第2篇 再探设计模式
第2章 命令模式 (已看)
第3章 享元模式 (已看)
第4章 观察者模式 (已看)
第5章 原型模式 (已看)
第6章 单例模式 (已看)
第7章 状态模式 (已看)
第3篇 序列型模式
第8章 双缓冲 (已看)
第9章 游戏循环 (已看)
第10章 更新方法 (已看)
第4篇 行为型模式
第11章 字节码 (已看)
第12章 子类沙盒 (已看)
第13章 类型对象 (已看)
第5篇 解耦型模式
第14章 组件模式 (已看)
第15章 事件队列 (已看)
第16章 服务定位器 (已看)
第6篇 优化型模式
第17章 数据局部性 (已看)
第18章 脏标记模式 (已看)
第19章 对象池 (已看)
第20章 空间分区 (已看)
第1章 架构,性能和游戏
1.1 什么是软件架构
这本书关于代码的组织方式
1.1.1 什么是好的软件架构
第一个关键部分是,架构意味着变化.衡量一个设计好坏的方法就是看它应对变化的灵活性
1.1.2 你如何做出改变
一旦你理解了问题和它涉及的代码,则实际的编码有时是微不足道的
1.1.3 我们如何从解耦中受益
你可以用一堆方式来定义"解耦",但我认为如果两块代码耦合,意味着你必须同时了解这两块代码.如果你让它们解耦,那么你只需了解其一.
当然,对解耦的另一个定义就是当改变了一块代码时不必更改另外一块代码.很明显,我们需要更改一些东西,但是耦合得越低,更改所波及得范围就越小
1.2 有什么代价
良好的架构需要很大的努力及一系列准则.每当你做出一个改变或者实现一个功能时,你必须很优雅地将它们融入到程序的其余部分.你必须非常谨慎地组织代码并保证其在开发周期中经过数以千计的小变化之后仍然具有良好的组织性
1.3 性能和速度
没有人可以在纸上设计出一个平衡的游戏.这需要迭代和实验.
1.4 坏代码中的好代码
原型(把那些仅仅在功能上满足一个设计问题的代码融合在一起)是一个完全正确的编程实践
1.5 寻求平衡
开发中我们有几个因素需要考虑
1. 我们想获得一个良好的架构,这样在项目的生命周期中便会更容易理解代码
2. 我们希望获得快速的运行时性能
3. 我们希望快速完成今天的功能
这些目标至少部分是相冲突的.好的架构从长远来看,改进了生产力,但维护一个良好的架构就意味着每一个变化都需要更多的努力来保持代码的干净
最快编写的代码实现却很少是运行最快的.相反,优化需要消耗工程时间.一旦完成,也会使代码库僵化:高度优化过的代码缺乏灵活性,很难改变
完成今日的工作并担心明天的一切总伴随着压力.但是,如果我们尽可能快的完成功能,我们的代码库就会充满了补丁,bug和不一致的混乱,会一点点地消磨掉我们未来的生产力
这里没有简单的答案,只有权衡
1.6 简单性
1.7 准备出发
抽象和解耦能够使得你的程序开发变得更快和更简单.但不要浪费时间来做这件事,除非你确信存在问题的代码需要这种灵活性
在你的开发周期中要对性能进行思考和设计,但是要推迟那些降低灵活性的,底层的,详尽的优化,能晚则晚
尽快地探索你的游戏的设计空间,但是不要走得太快留下一个烂摊子给自己.毕竟你将不得不面对它
如果你将要删除代码,那么不要浪费时间将它整理得很整洁.摇滚明星把酒店房间弄得很乱是因为他们知道第二天就要结账走人.
但是,最重要得是,若要做一些有趣得玩意,那就乐在其中地做吧
第2章 命令模式
"将一个请求(request)封装成一个对象,从而允许你使用不同的请求,队列或日志将客户端参数化,同时支持请求操作的撤销和恢复"
我想你也和我一样觉得这句话晦涩难懂.
首先,它的比喻不够形象.在软件界之外,一词往往多义."客户(client)"指代同你有着某种业务往来的一类人.据我查证,人类(human beings)是不可"参数化"的
其次,句子的剩余部分只是列举了这个模式可能的使用场景.而万一你遇到的用例不在其中,那么上面的阐述就不太明朗了.
我对命令模式的精炼概括如下: 命令就是一个对象化(实例化)的方法调用(A command is a reified(具象化) method call)
这个术语意味着,将某个概念(concept)转化为一块数据(data),一个对象,或者你可以认为是传入函数的变量等.
GOF后面这样补充到: 命令就是面向对象化的回调(Commands are an object-oriented replacement for callbacks)
一些语言的反射系统(Reflection system)可以让你在运行时命令式地处理系统中的类型.你可以获取到一个对象,它代表着某些其他对象的类,你可以通过它试试看这个类型能做些什么.话句话说,反射是一个对象化的类型系统
2.1 配置输入
简单实现
void InputHandler::handleInput() { if (isPressed(BUTTON_X)) jump(); else if (isPressed(BUTTON_Y)) fireGun(); else if (isPressed(BUTTON_A)) swapWeapon(): else if (isPressed(BUTTON_B)) lurchIneffectively(); }