静态类和单例模式之间存在什么实际的区别?
两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?
静态类和单例模式之间存在什么实际的区别?
两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?
当前回答
扩展Jon Skeet的答案
单例和一堆静态方法之间的最大区别是,单例可以实现接口(或从有用的基类派生,尽管这是不太常见的IME),因此您可以将单例作为“另一个”实现来传递。
当单元测试一个类时,单体更容易处理。无论您将单例作为参数(构造函数、setter或方法)传递到何处,您都可以替换单例的一个被嘲笑或存根的版本。
其他回答
下面是静态类和单例之间的一些主要区别:
1.Singleton是一种模式,而不是像static那样的关键字。因此,对于创建静态类,静态关键字就足够了,而对于单例,则需要为单例编写逻辑。
2.单例类必须具有私有的默认实例构造函数,而静态类不能包含任何实例构造函数。
3.静态类既不实例化也不扩展,而单例类可以实例化。
4.静态类是隐式密封的,但单例类必须修饰为显式密封的。
5.单例可以实现接口或从另一个类继承,但静态类既不实现接口,也不从任何其他类扩展。
6.我们不能用静态类实现依赖注入,但单例类可以实现DI,因为它可以是接口驱动的。静态类的作用域位于应用程序域级别,因为它由CLR管理,而单例对象的作用域则跨越应用程序生命周期。
7.静态类不能有任何析构函数,但单例类可以定义析构函数。
8.单例类实例可以作为参数传递给另一个方法,而静态类不能传递,因为它只包含静态成员。
扩展Jon Skeet的答案
单例和一堆静态方法之间的最大区别是,单例可以实现接口(或从有用的基类派生,尽管这是不太常见的IME),因此您可以将单例作为“另一个”实现来传递。
当单元测试一个类时,单体更容易处理。无论您将单例作为参数(构造函数、setter或方法)传递到何处,您都可以替换单例的一个被嘲笑或存根的版本。
单例只不过是一个类上的一次写入静态变量,一旦初始化,它总是引用自身的同一实例。
因此,您不能“使用单例代替静态变量”,也不能通过使用单例避免静态变量中的状态。
单例的优点只有一点:即使其他代码尝试重新初始化它一千次,它也不会被重新初始化。这对于像网络处理程序这样的东西来说非常棒,如果一个实例在等待响应的过程中被另一个实例替换,它会很糟糕。
除非你想要一个没有任何装置的整个应用程序,所有地方都是静态的-那么单例对于这些情况是有意义的,因为我们不能依靠缺少人为错误作为唯一的保证不会覆盖某些内容。
但要注意,单身汉并不能保证不会在任何地方生活。你的网络处理程序本身也可能依赖于其他单身者,等等。。。了不起的
而且,目前还没有编译器可以确保在编译时,单例是所有状态所在的地方,或者任何其他这样的想法所在的地方。在具有单例的类上可以有一百个静态变量。单例可以访问静态变量。编译器不会在意。
因此,我要提醒任何人,不要假设使用单例可以保证任何有关州生活的信息。它唯一的保证就是它是其类的唯一实例。这也是它唯一的优势。
其他答案所声称的单线图的任何其他优点都是编译器无法保证的,并且可能因语言而异。依赖注入是一种可能依赖于单例的补充模式,尽管它可能是或可能不是给定语言中的最佳解决方案或唯一解决方案。在缺少泛型的语言中,或者在调用静态访问器和函数时设置了任意限制,诉诸单例模式可能确实是解决给定问题的最佳解决方案。
在Swift这样的语言中,Singleton根本不需要获得依赖注入、可测试代码、良好管理的状态、线程安全访问器、多态性等。然而,它对于保证单一实例仍然有用。
概括一下:单例不过是一个静态变量,它可以防止给定类的多个实例存在,并防止单个实例被新实例覆盖。就这样,句号,句号。
静态类示例
public class Any {
private static Any instance = new Any();
private Singleton() {
System.out.println("creating");
}
}
单例模式只存在一个实例:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
System.out.println("creating");
if (instance != null) {
throw new RuntimeException("Imposible create a new instance ");
}
}
}
我将努力超越WTMI和WTL;DR响应。
单身者是一个物体的实例。。。句点
你的问题基本上是问类和该类的实例之间的区别。我认为这很清楚,不需要详细说明。
singleton的类通常采取步骤来确保构建一个实例;这很聪明,但不是必须的。
示例:var connection=connection.Instance;
假设这是Connection类:
public sealed class Connection
{
static readonly Connection _instance = new Connection();
private Connection()
{
}
public static Connection Instance
{
get
{
return _instance;
}
}
}
请注意,您可以在该类上抛出一个接口并模拟它以进行测试,这是静态类无法轻易做到的。