在开始我的下一个大项目之前,我已经在游戏编程表单这本书中浏览了所有的设计模式。除此之外,我还在更广泛的背景下读到了关于它们的文章。我很难理解的是命令模式,特别是游戏AI中使用它的部分。
作者说:
这里选择命令的AI和执行命令的参与者代码之间的解耦给了我们很大的灵活性。我们可以为不同的演员使用不同的人工智能模块。或者我们可以根据不同的行为混合和匹配人工智能。想要更有侵略性的对手吗?只需插入一个更具侵略性的人工智能,为其生成命令。事实上,我们甚至可以将AI栓到玩家的角色上,这对于游戏需要在自动驾驶上运行的演示模式很有用。
这部分让我认为,使用命令模式的要点是能够将不同的AI模块与不同的角色混合。这个功能不是可以通过一个简单的接口实现的吗?在所有其他的、更一般的书籍中,这种模式的主要好处是:推迟执行、队列命令、日志记录和撤消功能。
因此,概括地说:即使我不需要它提供的任何核心功能,命令模式对于参与者来说对于解耦游戏AI有用吗?
发布于 2018-12-10 13:38:22
只是想对罗伯特·哈维( Robert )已经很棒的答案作了一点补充,也许你会对此有更多的了解:
这个功能不是可以通过一个简单的接口实现的吗?在所有其他的、更一般的书籍中,这种模式的主要好处是:推迟执行、队列命令、日志记录和撤消功能。
在这种情况下,您将直接利用接收方,而不是将此命令抽象放在中间。
假设我缓存了一个ICommandable接口,而不是使用命令。这在功能上有什么不同?我知道这在结构上是不同的:我完全忽略了命令对象部分,但我看不出这里的解耦优势是什么。在这两种情况下,在创建命令/调用接口函数时,我都需要知道接收方是什么。我是不是遗漏了什么?
首先,如果您想在您的系统中引入新的命令,那么需要对这个ICommandable接口进行相当深入的集中更改。此外,添加到该接口中的每个新函数都必须由实现该接口的每个具体Commandable来实现,如果有多个扩展,这种扩展就会特别昂贵。
其次,它不允许你把新的功能夹在调用者和接收者之间。撤消、日志记录、队列和并行化只是您可能希望在调用方和接收方之间添加(甚至可能是事后发现)的功能的一些例子。
在我的例子中,在所有这些事情之上,我们还拥有由第三方注册的命令,这些第三方的插件在运行时由用户加载(我们使用工厂模式允许这样的注册和按名称实例化命令)。新命令的注册将使该命令自动显示在UI中,并且现在本机代码和我们的嵌入式脚本语言都可以访问该命令。它允许用户以各种方式调用该命令,例如单击GUI元素或在“命令”(脚本)控制台中键入命令,或在自己的文件中编写脚本,然后将其作为插件或编写C++插件并构建并动态加载。您可能不需要所有这些花言巧语,但它们是当您将命令模式与工厂结合时,您可以得到什么样的丰富行为的额外例子。
但是,回到你可以夹在中间的功能,在我们的例子中,由于第三方编写的插件(可能并不总是编写最健全的代码)可以注册命令以供执行,一些写得不好的插件可能会崩溃,使我们的主机应用程序也随之崩溃。因此,我们实际上启动了一个单独的进程,并在那里使用IPC执行命令,以便在该命令成功的情况下同步更改。这已经产生了实际效果,使我们的主机应用程序几乎是“防崩溃”。
这只是另一个功能的例子,你可以夹在调用者和接收者之间。它在我的经验中是非常有用的,它为我认为相当微不足道的前期成本提供了很大的喘息空间(尽管我可能认为它是微不足道的,部分原因是我在很久以前就已经以某种形式使用了这种基本模式)。
发布于 2018-10-15 17:31:07
这个功能不是可以通过一个简单的接口实现的吗?
不完全是。模式中还有一个对象充当调用方和接收方之间的中介。
[Caller] --> [Interface] --> [Command object] --> [Receiver]这就是脱钩的原因。呼叫者对听话者一无所知,听话人也不知道呼叫者的任何情况。另一个了解接收方和调用方的软件在运行时将对象连接起来。
这种模式经常出现在UI技术中,如WPF,其中使用Command对象而不是普通事件。它便于使用(MVVM),其中UI与底层业务逻辑解耦。
即使我不需要它提供的任何核心功能,命令模式对于参与者来说对于解耦游戏AI也很有用吗?
那么,解耦是Command提供的“核心功能”,所以您必须决定是否需要这种级别的解耦。
进一步阅读
https://softwareengineering.stackexchange.com/questions/380067
复制相似问题