1

在 AI 类中,有一个成员需要每 n 毫秒访问数百或数千次,例如,需要访问 LPDIRECT3DDEVICE3D 才能绘制任何内容。

曾经有一个全球性的,但这似乎不对。在我的研究中,我找到了 OP 问题的答案:

jalf“这很痛苦,所以这是一个警钟:我做错了。很多对象不需要知道屏幕缓冲区。我该如何解决这个问题?`)” @这个答案alinea 8

基本上我想知道如何对待这样一个全局变量,还有哪些其他选择?

4

3 回答 3

0

一种好的方法是让您都想使用 A::member 的对象在构造时使用数据结构(弱指针或原始指针的向量、指针映射等)注册自己,然后在您想要应用 A 时: :member 到每个对象,您可以遍历所有已注册的对象并处理每个对象的请求。请注意,在这里使用全局变量很容易陷入陷阱——尽量避免它。

如果您有不同类型的对象(没有继承层次结构),您可以使用类型擦除来存储每个对象的函数指针(或函数对象,如 boost::function),该对象将采用 A::member 并将其应用于该对象。这将允许任何抽象对象使用 A::member 而无需知道您的 x 个对象的类型。让函数匹配可能就像向每个对象添加类似格式化的成员函数或执行 boost::bind 以将执行工作的调用包装成匹配的格式一样简单。

这种方法消除了许多样板代码,并为您提供了各种新对象类型的轻松可扩展性,以便在某个指定的通知时间全部使用 A::member。

于 2012-08-14T20:26:16.503 回答
0

您的选择归结为:如果函数需要数据,则该数据必须:

  1. 作为参数传递给函数,或者
  2. 在函数可以有效查询它的地方。

(我将忽略 3. 或由函数本身生成。)

如果你想通过A::member,你有几个选择。您可以将数据放在上下文对象中并传递它(如果您有一些想要传递的这些成员,并且恰好在存在单元测试的情况下运行良好,这可能会很有效)。您可以将数据直接传递到函数中。您可以将数据传递给某些东西,然后再将其传递给函数。您可以使用消息传递。您可以使用更间接的机制,例如发布/订阅队列。您可以选择这些中介对他们传递的数据类型了解多少。当您将数据从一个地方传递到另一个地方时,所有这些都意味着源、传输和目的地之间的各种耦合。充其量这种耦合可能会在规模上令人恼火。在最坏的情况下,这可能是一个严重的设计或安全缺陷。

如果你想把A::member它放在可以查询的地方,你也有几个选择。全局变量是 1。可以访问的数据存储(例如文件、数据库、服务、缓存、HTTP 资源)是另一个。其中每一个都有含义:您需要考虑谁可以访问数据以及如何访问。如果访问很容易(例如在全局变量中),那么您将面临如何在不破坏数据客户端的情况下发展系统的问题。在测试代​​码时,您也可能会遇到问题。充其量这种耦合可能会在规模上令人恼火。在最坏的情况下,它可能是一个严重的设计缺陷并导致几乎无法测试的代码。

如果您想传递数据,但您不喜欢需要传递数据的位置数量,那么您的另一个攻击角度是限制需要您的数据的函数的数量。即整合您的代码,以便真正需要了解的代码片段更少A::member。Facade、Bridge、Observer 和 Abstract Base Class 等各种模式可能会在语言级别为您提供帮助。发布-订阅和回调等架构模式也可能会有所帮助。研究解耦重构依赖消除的主题以获得灵感。

那么这些方法中哪一个是正确的呢?没有一种正确的方法。您需要查看您的特定案例,权衡该案例的选项和权衡,然后选择您最喜欢的一个。

于 2012-08-15T23:35:42.443 回答
0

我能想到的一件事是将 A::member 传递给所有需要访问它的函数,但这将是一个荒谬的数量。

有很多方法——它们遍布您每天使用的程序。

  • 你可以参考
  • 通过参考(如您所述)
  • 在某些情况下使用多个实例
  • 使用方法抽象出调用方法实际上需要 3 次调用的事实(最少知识原则)
  • 使用更小、更专业的对象
  • 考虑其他形式的抽象和/或包装
  • 在某些地方考虑其他设计模式

刚开始编写程序——不要盲目,因为你最终可能会得到高耦合——观察使用模式并相应地重构和重组。这是全局变量不好的原因之一——它们很难根除,但这几乎是删除具有大量引用的变量时必须经历的过程。

于 2012-08-15T08:30:08.853 回答