【发布时间】:2010-09-26 00:36:23
【问题描述】:
在回答这个问题 (https://stackoverflow.com/questions/352317/c-coding-question#352327) 时,我很想知道...
将静态类等同于实现单例模式的非静态类实例化有什么危险吗?
【问题讨论】:
标签: c# design-patterns static singleton
在回答这个问题 (https://stackoverflow.com/questions/352317/c-coding-question#352327) 时,我很想知道...
将静态类等同于实现单例模式的非静态类实例化有什么危险吗?
【问题讨论】:
标签: c# design-patterns static singleton
唯一对我来说似乎很明显的是静态类基本上只是范围函数的集合(在这里明确避免“方法”),并且单例仍然是您可以实例化的东西,即使您只能有 1 . 1 > 0.
您可以将单例作为参数传递给需要某个接口的对象的东西,您不能在任何地方传递静态类(通过一些反射技巧除外)
【讨论】:
在许多方面,静态类和单例是相似的。一个很大的区别是单例可能会实现一些接口,而这对于静态类是不可能的。例如,Comparer<T>.Default / EqualityComparer<T>.Default 提供(通过接口)在排序/字典使用中使用项目的能力。
在标准序列化框架中使用单例也是可能的(虽然很棘手)。使用静态类,您必须手动管理任何状态持久性。
【讨论】:
它并不完全等价。例如,您可以将对单例实例的引用作为参数传递,而静态类不能这样做,因为没有实例。
“危险”是什么意思?
【讨论】:
正如罗伯特·古尔德指出的那样,您对建筑的控制权松懈了。您还会遇到更加晦涩难懂的施工问题。静态类很快就会以静态初始化块结束。这些块在有人第一次引用您的类型时被调用,并且此顺序可能没有您想像的那样定义好。因此,这些静态初始化程序的运行顺序可能会在您没有计划的情况下发生变化,并可能导致奇怪的错误。
【讨论】:
我可以看到静态类的主要危险是在编写单元测试时它们更难模拟。使用单例,您可以通过在其位置注入不同的类来测试特定功能的方式来创建它,而使用静态类则不是那么容易。
【讨论】:
不确定 C#,但在 C++ 中,静态对象会在初始化时被初始化,并且您无法直接控制它(尤其是在多线程应用程序中)。所以你需要一个函数来调用你的对象,而不是直接调用它(除非你想要不可移植的代码)
【讨论】:
正如 Robert 之前所说,初始化是静态类的主要缺点。 静态类通常会在最后可能的时刻延迟初始化。但是,您会失去对确切行为的控制,并且静态构造函数很慢。
通常使用静态类来保存全局数据。全局数据会在您的其他对象/类之间创建隐式依赖关系。所以在改变这个“全局对象”时一定要小心。可能会破坏您的应用程序。
【讨论】:
我认为在单例实现的上下文中没有任何危险。我经常这样做,通过静态类实现单调。从逻辑上讲,如果对象引用是单独且唯一的,则它不是必需的。
【讨论】: