对于桌面应用程序。这只是一个一般性问题,可能只需要一般性答案。
9 回答
具有静态数据成员的静态类?但谁在乎。静态数据成员只是具有更政治正确包装的全局变量。
不要让时尚凌驾于你的常识之上。使用普通的旧全局变量没有任何问题。单例模式通常是多余的,打字很烦人,当你单步调试代码时也很烦人。
假设您使用的是 C/C++,我建议您不要将全局变量作为从堆中分配内存的类实例。它们将使您更难使用检查内存泄漏的工具。将全局声明为一个指针,在 main() 的开头新建它,在末尾删除它。
6 条评论后编辑:考虑日志记录。您不希望能够从应用程序的任何位置向日志写入一行吗?在没有全局可见的东西来进行日志记录的情况下,您如何具体实现这一点?如果你想要全局可见的东西,那么继续让它全局可见。
答案取决于语言。我最近遇到了一个人,他的公司开发了可在许多流行手机上运行的 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 软件公司,他们可以很容易地将不同的部分组合在一起以供不同的客户使用。
我真的很喜欢这种编程方式,因为我可以看到正在发生的一切,并且我的私有数据结构受到保护,不会被窥探 :-)
首先,假装单身比全局更好或更容易接受是没有意义的。单例只是一个装扮成 OOP 的全局变量。还有一堆其他问题。
另一种选择当然是没有全局数据。而不是你的类在某处访问一些静态(全局)变量,而是将数据传递给它的构造函数。是的,这意味着您必须向构造函数添加一些参数,但这是一件坏事吗?它使类的依赖关系显式。我可以简单地通过在构造函数中向它提供不同的对象来测试该类,而如果它依赖于全局数据,那么这些全局变量必须存在于我的测试中,这很混乱。
同样,我可以轻松地重构,因为除了直接传递给对象的内容之外,对类没有任何神奇的依赖。
线程安全变得更容易管理,因为您不再让所有对象与同一个全局实例进行通信。相反,可以将它们传递给类的单独实例。
我不在乎是否不推荐单例或全局变量。如果我觉得这是实现它的最合乎逻辑的方式,那么我会继续使用它。
这完全取决于您要解决的问题。您忽略了这一关键信息。如果您正在寻找一个包罗万象的解决方案,那么没有。只有我们在适用时应用的模式。
我在全局变量和单例变量中看到的最常见的问题是,在使用线程时可能会出现不良行为。在这种情况下,您应该始终使用执行范围作为基本单元。这是 OO 编程的优势之一 - 您可以使用对象成员来保存所有相关数据,而不必担心意外的线程混乱。这与不支持 OO 的编程语言形成鲜明对比,在这种语言中,您必须通过参数传递数据。
另一个常见的问题往往是组织性的——当可以随时读取/写入数据时,很难准确地理解大型系统中数据的来源。根据我的经验,这更多是开发人员的问题,而不是代码本身的问题。除非您正在研究那些似乎主要出现在编程书籍中作为困难问题示例的数亿行巨型系统之一,否则您将能够在相当短的时间内搜索整个代码库以查找特定项目一段的时间。必要的下一步是定期审核代码库,以确保不会随机分配全局/静态变量。这对许多开发方法来说都是一种厌恶,但对于一定规模和复杂性的系统来说,这是一个完美可行的解决方案。
一个常见的解决方案是使用单实例类而不是单例/全局变量。
您的应用程序将负责确保您只有一个实例。
这个解决方案有点糟糕,因为你不能阻止人们实例化你的类(不是单例),所以它必须是一个内部类。
不过,我不会太在意关于单例模式的所有宗教战争——如果我认为它适合我的需要,我通常会使用它。
在使用全局变量和单身人士并看到一切都变得一团糟之后,我想出了这个解决方案。
make every global variable a member of a class. Logically every global variable belongs to application (or system). just create an application class. define global objects as properties. so they are created when first called.
create a singleton for application class, so you can access it globally. This will be the only singleton in your code. well, at the end it is like system.out or system.in objects in java.
note: I know that, this is a very old question, but still popular.
全局变量在小程序中很好,但是当它们变大时,当有人通过“哦,我将设置这个全局变量然后问题消失”进行更改或修复错误时,你开始得到奇怪的副作用