好吧,全局变量被谴责,单身人士被鄙视,还有什么选择?

时间:2008-12-13 14:32:22

标签: singleton global-variables

对于桌面应用程序。这只是一个普遍的问题,可能只需要一般的答案。

9 个答案:

答案 0 :(得分:34)

具有静态数据成员的静态类?但谁在乎。静态数据成员只是全局变量,包装更具政治正确性。

不要让时尚超越你的常识。使用普通的旧全局变量没有任何问题。单例模式通常是过度杀戮和令人讨厌的类型,当你单步执行代码来调试它时会很烦人。

假设您正在使用C / C ++,我建议您不要使用全局变量作为从堆中分配内存的类实例。它们会使您更难使用检查内存泄漏的工具。将全局声明为指针,在main()的开头新建它,最后删除它。

6评论之后的编辑:想想伐木。您不希望能够从应用程序的任何位置在日志中写入一行吗?如果没有全局可见的日志记录,您是如何具体实现的?如果你想要全局可见的东西,那么继续使它全局可见。

答案 1 :(得分:14)

答案取决于语言。我最近遇到了一个人,他的公司开发了在许多流行手机上运行的USB堆栈(例如,所以你的手机可以与你的电脑通话)。他们的商店有一条规则,所有C程序都必须是可重入的。实际上,这意味着它们不是全局变量,而是为每个例程使用额外的参数;该参数指向应该在例程之间保持的状态。

我一直使用这种技术进行状态抽象。示例:摄影图像的阅读器抽象:阅读器一次可以访问一个像素;它必须知道打开文件描述符,图像中的当前位置是什么,依此类推。所有这些信息都会进入私有C结构或C ++类的私有成员。没有全局变量。外界看到:

typedef struct Pnmrdr_T *Pnmrdr_T;

struct Pnmrdr_T *Pnmrdr_new(FILE *);
pixel Pnmrdr_get(Pnmrdr_T);
void Pnmrdr_close(Pnmrdr_T);
void Pnmrdr_free(Pnmrdr_T *rp); // frees memory and sets *rp = NULL

这种编程风格与OO方法非常相似。

为什么比全局变量更好? 没有意外。如果出现问题或者你想要添加一个功能,你知道传入的值都是显式的。此外,你知道你可以将很多模块插在一起,除非你明确地在它们之间传递状态,否则它们不会干涉。我在手机业务方面的联系人说,这个属性对他的公司来说是巨大的 - 他们是一个OEM软件服装,他们可以轻松地为不同的客户插入不同的部分。

我非常喜欢这种方式编程,因为我可以看到正在发生的一切,并保护我的私人数据结构免受窥探: - )

答案 2 :(得分:8)

首先,假装单词在某种程度上比全局变量更好或更可接受是没有意义的。单身人士只是一个看起来像OOP的全球性服装。抛出一堆其他问题。

另一种选择当然是拥有全局数据。而不是您的类在某处访问某些静态(全局)变量,而是将数据传递给其构造函数。是的,这意味着你必须向构造函数添加一些参数,但这是件坏事吗?它使类的依赖项显式化。我可以简单地通过在构造函数中为它提供不同的对象来测试类,而如果它依赖于全局数据,那些全局变量必须存在于我的测试中,这很麻烦。

同样,我可以轻松地重构,因为除了直接传递给对象的类之外,没有任何魔法依赖。

线程安全性变得更容易管理,因为您不再让所有对象与同一个全局实例进行通信。相反,它们可以传递给类的单独实例。

答案 3 :(得分:3)

我不在乎是否不建议使用单例或全局变量。如果我觉得这是实现它的最合理的方式,那么我将继续使用它。

答案 4 :(得分:2)

这完全取决于你试图解决的问题。您遗漏了这一关键信息。如果你正在寻找一个总体解决方案,那就没有一个。在适用的情况下,我们只会应用模式。

答案 5 :(得分:1)

我在全局和单身人士中看到的最常见的问题是,在使用线程时你会冒不良行为。在这种情况下,您应始终使用执行范围作为基本单位。这是OO编程的优势之一 - 您可以使用对象成员保存所有相关数据,而不必担心意外的线程混乱。这与具有非OO功能的编程语言形成鲜明对比,在这种语言中,您必须通过参数向下传输数据。

另一个常见的问题往往是组织性的 - 当一个大型系统中的数据可以随时读取/写入时,很难准确理解数据的来源。根据我的经验,这是开发人员的问题,而不是代码本身。除非你正在研究那些似乎主要出现在编程书籍中作为难题问题的数千万行系统之一,否则你将能够在相当短的时间内搜索整个代码库中的特定项目。一段的时间。必要的下一步是定期审核代码库,以确保不会随机分配全局/静态变量。这对许多开发方法来说都是一种诅咒,但对于一定规模和复杂度的系统来说,这是一个非常可行的解决方案。

答案 6 :(得分:0)

对此的常见解决方案是使用单实例类而不是单例/全局变量。

您的申请将负责确保您只有一个实例。

这种解决方案有点糟糕,因为你不能阻止人们实现你的课程(不是单身),所以它必须是一个内部课程。

我对关于单身模式的所有religious wars都不太在意 - 如果我认为它符合我的需要,我通常会使用它。

答案 7 :(得分:0)

全局变量在小程序中很好,但是当它们变大时,当有人通过“哦,我只是设置全局并且问题消失”进行更改或修复错误时,你会开始产生奇怪的副作用

答案 8 :(得分:0)

使用全局变量和单身人士后,看到一切都搞砸了,我找到了这个解决方案。

  1. 使每个全局变量成为一个类的成员。逻辑上,每个全局变量都属于应用程序(或系统)。只需创建一个应用程序类。将全局对象定义为属性。所以它们是在第一次调用时创建的。

  2. 为应用程序类创建单例,以便您可以全局访问它。这将是代码中唯一的单例。 好吧,最后它就像java中的system.out或system.in对象。

  3. 注意:我知道,这是一个非常古老的问题,但仍然很受欢迎。