放弃Globals吗?

时间:2020-03-05 18:54:50  来源:igfitidea点击:

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

几个解决方案:

  • 我可以使用静态字段(但这相当于全局字段)

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

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

解决方案

回答

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

编辑:选项实际上是以下内容:

  • 将根引用存储在节点中
  • 根本不存储根引用
  • 将根引用存储在全局中
  • 将根引用存储在堆栈上(我的建议是访问者模式或者递归)

我认为这是所有可能性,没有选择5.

回答

为什么要取消全局变量?我理解全局变量对所有方面都是坏的烙印,但是有时仅具有包含所有元素的全局数据结构是最快的解决方案。

我们需要权衡取舍:代码清晰,减少将来的性能问题。这就是"不要优化"的意思。由于我们处于优化阶段,因此有时有必要减少一些可读性和良好的编程习惯以提高性能。我的意思是,按位黑客无法读取,但速度很快。

我不确定我们有多少个树对象,但是我个人会选择第一种。除非我们要处理成千上万的树,否则指针实际上不会等于几个字符串。如果内存确实是一个非常重要的问题,请尝试两种方法(它们似乎很容易实现),然后通过探查器运行它。或者使用出色的Process Explorer。

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

回答

点#1是过早的内存优化。 #2是过早的性能优化。我们是否对应用程序进行了配置文件以确定是否是内存或者CPU瓶颈给我们造成了问题?如果不是,为什么要牺牲一个更易于维护的设计来实现对用户没有帮助的"优化"?

我强烈建议我们选择#2. 每当我们存储可以计算的内容时,我们所做的就是缓存。缓存有时是个好主意,但这也是维护的麻烦。 (例如,如果通过更改节点的父节点将节点从一棵树移到另一棵树,却又忘记更新根字段怎么办?)如果不需要,不要缓存。

回答

我们可以从TreeView派生一个类,然后添加一个单例静态属性。这样,我们可以有效地添加一个引用该类的单个实例的全局字段,但具有将其命名空间限定于该类的优点。

回答

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

根据Java如何将节点与其父节点关联,最终可能与#1相同。 (我不确定,我将不得不对其进行概要分析)

回答

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