取消全局?

Doing away with Globals?

提问人:Allain Lalonde 提问时间:9/16/2008 最后编辑:James McMahonAllain Lalonde 更新时间:10/2/2009 访问量:425

问:

我有一组深度在 20 年代的树对象。此树中的每个节点都需要访问其树的根目录。

几种解决方案:

  1. 每个节点都可以直接存储对根目录的引用(浪费内存)
    • 我可以通过“上升”(浪费周期)在运行时计算根
    • 我可以使用静态字段(但这相当于全局字段)

有人可以提供一种不使用全局(在任何变体中)但分别在内存或周期中比 #1 或 #2 更有效的设计吗?

编辑:由于我有一组树,我不能简单地将其存储在静态中,因为很难区分树。(感谢 Maccullt)

C# Java OOP 全局变量

评论

0赞 maccullt 9/16/2008
目前尚不清楚您是否有一片树林,在这种情况下,您需要多个树根,或者您是否有一个树根。在森林的情况下,我不明白静力学如何解决您的问题,难道您不需要每棵树一个根并且每棵树都会引用其根(解决方案 1)吗?

答:

6赞 Niall 9/16/2008 #1

将根作为参数传递给节点中需要它的任何函数。

编辑:选项实际上如下:

  1. 将根引用存储在节点中
  2. 根本不存储根引用
  3. 将根引用存储在全局
  4. 将根引用存储在堆栈上(我的建议,访问者模式或递归)

我认为这是所有的可能性,没有选项 5。

评论

0赞 Allain Lalonde 9/16/2008
唉,访客图案整洁。我没有想到这一点。
0赞 Jonathan Allen 9/16/2008
发现当某些事情发生变化时,这往往会非常痛苦,尤其是当调用堆栈变得更深时。
0赞 Allain Lalonde 9/16/2008
我没有将其解释为递归。我可以有一段代码遍历树并在每个节点上执行。该代码将具有对根目录的引用。
3赞 David J. Sokol 9/16/2008 #2

为什么需要取消全局变量?我理解全局是坏的耻辱,但有时只是拥有一个包含所有元素的全局数据结构是最快的解决方案。

您需要做出权衡:代码清晰度和减少未来性能问题。这就是“不要优化”的意思。由于您处于优化阶段,有时有必要削减一些可读性和良好的编程实践,以支持性能。我的意思是,按位黑客是不可读的,但它们很快。

我不确定你有多少树对象,但我个人会选择选项一。除非你要处理数千+棵树,否则指针实际上不会超过几根弦。如果内存确实是一个超级重要的问题,请尝试这两种方法(它们似乎很容易实现)并通过分析器运行它。或者使用优秀的Process Explorer

编辑:我正在开发的一个应用程序有一个包含大约 55K 节点的节点树。我们构建树结构,但也维护一个用于 O(1) 查找的数组。比使用递归 FindNodeByID 方法时得到的 O(m*n) 要好得多。

评论

0赞 Mike Stone 9/16/2008
80k...??你担心不到十分之一的梅格......??听起来你正在为一个不存在的问题而感到压力
0赞 Allain Lalonde 9/16/2008
没有压力,只是好奇。我认为这是一个简洁的问题。
0赞 David J. Sokol 9/16/2008
归根结底,80K 是微不足道的。当我最初看到代码时,我非常“wtf”,直到我通过分析器运行它并意识到我们的字符串分配大约是它的 400 倍。
1赞 munificent 9/16/2008 #3

点 #1 是过早的内存优化。#2 是过早的性能优化。您是否分析了您的应用以确定内存或 CPU 瓶颈是否导致您出现问题?如果不是,为什么要牺牲一个更易于维护的设计来做一个对用户没有帮助的“优化”呢?

我强烈建议您选择#2。每当你存储一些你可以计算的东西时,你所做的就是缓存。有几次缓存是个好主意,但这也是一个令人头疼的维护问题。(例如,如果通过更改节点的父节点将节点从一棵树移动到另一棵树,但忘记同时更新根字段,该怎么办?如果不需要缓存,请不要缓存。

0赞 Phil Wright 9/16/2008 #4

您可以从 TreeView 派生一个类,然后添加一个单一实例静态属性。这样,您就可以有效地添加一个全局字段,该字段引用类的单个实例,但其好处是命名空间范围限定为该类。

0赞 Allain Lalonde 9/16/2008 #5

忽略对内部类的厌恶,我可以定义一个 Tree 类并将节点定义为内部类。每个节点都可以访问其树的状态,包括其根。

这最终可能与 #1 相同,具体取决于 Java 如何将节点与其父节点相关联。(我不确定,我必须对其进行分析)

评论

0赞 Niall 9/16/2008
我几乎可以肯定这将与#1相同,实际上没有其他方法可以实现它。
2赞 Daniel James 9/16/2008 #6

通常最好将根作为参数传递。如果您使用某种迭代器来导航树,另一种方法是在其中存储对 root 的引用。