静态VS.在SO中已经多次讨论过单身人士问题 然而,所有的答案都指出了单身人士的许多优点。 我的问题是 - 静态类比单例有什么优势? 为什么不每次只选择一个单身?
答案 0 :(得分:40)
静态类是您框中的技术工具 - 基本上是一种语言功能。
Singleton是一种建筑概念。
您可以使用静态类作为实现单例概念的方法。或者您可以使用其他方法。
如果您不小心,使用C#中的静态类会有两个潜在的危险。
答案 1 :(得分:23)
来自MSDN
静态类和类成员用于创建数据和函数 无需创建类的实例即可访问。静态的 类成员可用于分隔数据和行为 独立于任何对象标识:数据和功能不相关 无论对象发生什么变化都会发生变化。静态类可以 当依赖于类中没有数据或行为时使用 对象身份。
关键是静态类do not require an instance reference
。另请注意,语言和编译器专门启用了静态类。
Singleton类只是实现Singleton设计模式的用户编码类。单身人士的目的是restrict instantiation of an class to a single instance
。
如果您将每个静态类编码为单例,则每次使用它时都必须实例化该类。
即。
Console.WriteLine('Hello World');
会变成
Console c = Console.getInstance();
c.WriteLine('Hello World');
答案 2 :(得分:9)
我会说他们(通常)都是糟糕的解决方案。静态类有一些用例,主要是简单实用的(C#3.0中的扩展方法)。但是,随着任何程度的复杂性,可测试性问题开始出现。
假设A类依赖于静态类B.您希望单独测试A类。那很难。
所以你选择了Singleton。你有同样的问题 - A类依赖于单身B.你不能孤立地测试A类。
当B类具有其他依赖关系(例如命中数据库)或者是可变的(其他类可以改变其全局状态)时,问题会更加严重。
IoC(Inversion of Control)容器库是解决此问题的一种方法;它们允许您将Plain Old Classes定义为具有较长的使用寿命。当与模拟库结合使用时,它们可以使您的代码非常可测试。
答案 3 :(得分:6)
静态类更容易实现 - 我已经看到C#中的线程安全单例的许多尝试采用了朴素锁定方案,而不是依赖于运行时保证静态字段的一次性初始化(可选地在嵌套类中)延迟实例化。)
除此之外,我认为如果你需要传递对实现特定接口的对象的引用,那么单例是很好的,当'实现'应该是单例时,你不能用静态类做什么。
答案 4 :(得分:2)
我没有提到的一个考虑因素是,更喜欢使用类实例(单例或其DI等价物)的解决方案允许您提供一个类,代码的其他用户可以在其中定义扩展方法 - 因为扩展方法仅适用于非静态类作为this
参数。换句话说,如果您有一行:
GlobalSettings.SomeMethod();
然后在语法上,唯一可以通过GlobalSettings
访问的是你提供的成员。相反,如果GlobalSettings
是一个实例(单身或其他),那么消费者可以将他们自己的扩展添加到GlobalSettings
,否则他们将无法做到:
application.GlobalSettings.CustomSomethingOrOther();
或
GlobalSettings.Instance.CustomSomethingOrOther();