// 这里是具体命令。 classCopyCommandextendsCommand is // 复制命令不会被保存到历史记录中,因为它没有改变编辑器的状态。 method execute() is app.clipboard = editor.getSelection() returnfalse
classCutCommandextendsCommand is // 剪切命令改变了编辑器的状态,因此它必须被保存到历史记录中。只要方法 // 返回 true,它就会被保存。 method execute() is saveBackup() app.clipboard = editor.getSelection() editor.deleteSelection() returntrue
classPasteCommandextendsCommand is method execute() is saveBackup() editor.replaceSelection(app.clipboard) returntrue
// 撤销操作也是一个命令。 classUndoCommandextendsCommand is method execute() is app.undo() returnfalse
// 全局命令历史记录就是一个堆桟。 classCommandHistory is private field history: array of Command
// 后进... method push(c: Command) is // 将命令压入历史记录数组的末尾。
// ...先出 method pop():Command is // 从历史记录中取出最近的命令。
// 编辑器类包含实际的文本编辑操作。它会担任接收者的角色:最后所有命令都会 // 将执行工作委派给编辑器的方法。 classEditor is field text: string
method getSelection() is // 返回选中的文字。
method deleteSelection() is // 删除选中的文字。
method replaceSelection(text) is // 在当前位置插入剪贴板中的内容。
// 应用程序类会设置对象之间的关系。它会担任发送者的角色:当需要完成某些工 // 作时,它会创建并执行一个命令对象。 classApplication is field clipboard: string field editors: array of Editors field activeEditor: Editor field history: CommandHistory
// 应用程序(Application)类可对集合和迭代器进行配置,然后将其传递给客户 // 端代码。 classApplication is field network: SocialNetwork field spammer: SocialSpammer
method config() is if working with WeChat this.network = newWeChat() if working with LinkedIn this.network = newLinkedIn() this.spammer = newSocialSpammer()
// 远程服务接口。 interfaceThirdPartyTVLib is method listVideos() method getVideoInfo(id) method downloadVideo(id)
// 服务连接器的具体实现。该类的方法可以向腾讯视频请求信息。请求速度取决于 // 用户和腾讯视频的互联网连接情况。如果同时发送大量请求,即使所请求的信息 // 一模一样,程序的速度依然会减慢。 classThirdPartyTVClassimplementsThirdPartyTVLib is method listVideos() is // 向腾讯视频发送一个 API 请求。
method getVideoInfo(id) is // 获取某个视频的元数据。
method downloadVideo(id) is // 从腾讯视频下载一个视频文件。
// 为了节省网络带宽,我们可以将请求结果缓存下来并保存一段时间。但你可能无 // 法直接将这些代码放入服务类中。比如该类可能是第三方程序库的一部分或其签 // 名是`final(最终)`。因此我们会在一个实现了服务类接口的新代理类中放入 // 缓存代码。当代理类接收到真实请求后,才会将其委派给服务对象。 classCachedTVClassimplementsThirdPartyTVLib is private field service: ThirdPartyTVLib private field listCache, videoCache field needReset
constructor CachedTVClass(service: ThirdPartyTVLib) is this.service = service
// 享元类包含一个树的部分状态。这些成员变量保存的数值对于特定树而言是唯一 // 的。例如,你在这里找不到树的坐标。但这里有很多树木之间所共有的纹理和颜 // 色。由于这些数据的体积通常非常大,所以如果让每棵树都其进行保存的话将耗 // 费大量内存。因此,我们可将纹理、颜色和其他重复数据导出到一个单独的对象 // 中,然后让众多的单个树对象去引用它。 classTreeType is field name field color field texture constructor TreeType(name, color, texture) { ... } method draw(canvas, x, y) is // 1. 创建特定类型、颜色和纹理的位图。 // 2. 在画布坐标 (X,Y) 处绘制位图。
// 享元工厂决定是否复用已有享元或者创建一个新的对象。 classTreeFactory is static field treeTypes: collection of tree types static method getTreeType(name, color, texture)is type= treeTypes.find(name, color, texture) if (type == null) type = newTreeType(name, color, texture) treeTypes.add(type) return type
// 情景对象包含树状态的外在部分。程序中可以创建数十亿个此类对象,因为它们 // 体积很小:仅有两个整型坐标和一个引用成员变量。 classTree is field x,y field type: TreeType constructor Tree(x, y, type) { ... } method draw(canvas) is type.draw(canvas, this.x, this.y)
// 树(Tree)和森林(Forest)类是享元的客户端。如果不打算继续对树类进行开 // 发,你可以将它们合并。 classForest is field trees: collection of Trees
method plantTree(x, y, name, color, texture)is type= TreeFactory.getTreeType(name, color, texture) tree = newTree(x, y, type) trees.add(tree)
method draw(canvas) is foreach(tree in trees)do tree.draw(canvas)
游戏中所有的种族都有几乎同类的单位和建筑。 因此你可以在不同的种族上复用相同的 AI 结构, 同时还需要具备重写一些细节的能力。 通过这种方式, 你可以重写半兽人的 AI 使其更富攻击性, 也可以让人类侧重防守, 还可以禁止怪物建造建筑。 在游戏中新增种族需要创建新的 AI 子类, 还需要重写 AI 基类中所声明的默认方法。