静态类和单例模式之间存在什么实际的区别?

两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?


当前回答

是什么让你说单例或静态方法都不是线程安全的?通常,这两者都应该实现为线程安全的。

单例和一堆静态方法之间的最大区别是,单例可以实现接口(或从有用的基类派生,尽管在我的经验中这不太常见),因此您可以将单例作为“另一个”实现来传递。

其他回答

单例的另一个优点是它可以很容易地序列化,如果您需要将其状态保存到磁盘或远程发送到某个位置,这可能是必要的。

静态类别:-

无法创建静态类的实例。当加载包含类的程序或命名空间时,由.NET Framework公共语言运行库(CLR)自动加载。我们不能将静态类传递给方法。我们不能将静态类继承到C#中的另一个静态类。具有所有静态方法的类。更好的性能(静态方法在编译时绑定)

辛格尔顿:-

您可以创建对象的一个实例并重用它。当用户请求时,首次创建Singleton实例。您可以创建singleton类的对象并将其传递给方法。Singleton类没有说明继承的任何限制。我们可以处理单例类的对象,但不能处理静态类的对象。方法可以被重写。可以在需要时延迟加载(静态类总是加载的)。我们可以实现接口(静态类不能实现接口)。

与静态类的区别

JDK有单例和静态的例子,一方面java.lang.Math是带有静态方法的最终类,另一方面java.lang.Runtime是单例类。

单例的优点

如果您需要维护状态,那么单例模式比静态类更好,因为在静态类中维护状态会导致错误,特别是在并发环境中,如果没有多个线程进行适当的同步并行修改,则可能会导致竞争条件。如果Singleton类是一个沉重的对象,那么它可以被延迟加载,但静态类没有这样的优势,总是急切地加载。使用singleton,您可以使用继承和多态性来扩展基类、实现接口并提供不同的实现。由于Java中的静态方法不能被重写,它们会导致灵活性。另一方面,您可以通过扩展singleton类来重写它中定义的方法。

静态类的缺点

为单例编写单元测试比静态类更容易,因为只要需要单例,就可以传递模拟对象。

静态类的优点

静态类提供了比单例更好的性能,因为静态方法是在编译时绑定的。

单例模式有几种实现方式,每种实现方式都有优缺点。

Eager加载单例双重检查锁定单例按需初始化持有者习惯用法基于枚举的单例

详细描述每一个都太冗长了,所以我只需要链接到一篇好文章-你想知道的关于Singleton的所有信息

单例只不过是一个类上的一次写入静态变量,一旦初始化,它总是引用自身的同一实例。

因此,您不能“使用单例代替静态变量”,也不能通过使用单例避免静态变量中的状态。

单例的优点只有一点:即使其他代码尝试重新初始化它一千次,它也不会被重新初始化。这对于像网络处理程序这样的东西来说非常棒,如果一个实例在等待响应的过程中被另一个实例替换,它会很糟糕。

除非你想要一个没有任何装置的整个应用程序,所有地方都是静态的-那么单例对于这些情况是有意义的,因为我们不能依靠缺少人为错误作为唯一的保证不会覆盖某些内容。

但要注意,单身汉并不能保证不会在任何地方生活。你的网络处理程序本身也可能依赖于其他单身者,等等。。。了不起的

而且,目前还没有编译器可以确保在编译时,单例是所有状态所在的地方,或者任何其他这样的想法所在的地方。在具有单例的类上可以有一百个静态变量。单例可以访问静态变量。编译器不会在意。

因此,我要提醒任何人,不要假设使用单例可以保证任何有关州生活的信息。它唯一的保证就是它是其类的唯一实例。这也是它唯一的优势。

其他答案所声称的单线图的任何其他优点都是编译器无法保证的,并且可能因语言而异。依赖注入是一种可能依赖于单例的补充模式,尽管它可能是或可能不是给定语言中的最佳解决方案或唯一解决方案。在缺少泛型的语言中,或者在调用静态访问器和函数时设置了任意限制,诉诸单例模式可能确实是解决给定问题的最佳解决方案。

在Swift这样的语言中,Singleton根本不需要获得依赖注入、可测试代码、良好管理的状态、线程安全访问器、多态性等。然而,它对于保证单一实例仍然有用。

概括一下:单例不过是一个静态变量,它可以防止给定类的多个实例存在,并防止单个实例被新实例覆盖。就这样,句号,句号。

静态类不适用于任何需要状态的对象。它对于将一堆函数放在一起非常有用,例如Math(或项目中的Utils)。所以类名只是给了我们一个线索,我们可以在哪里找到函数,而不是更多。

Singleton是我最喜欢的模式,我用它在一个点上管理一些东西。它比静态类更灵活,可以保持其状态。它可以实现接口,从其他类继承并允许继承。

我在静态和单例之间选择的规则:

如果有一堆函数应该保持在一起,那么静态就是选择。任何其他需要对某些资源进行单一访问的内容都可以作为单例实现。