缺点:没有接口,扩展困难。
日志系统:在应用程序中,通常只需要一个日志系统,以避免在多个地方创建多个日志对象。这一般是由于共享的日志文件一直处于打开状态,所以只能有一个实例去操作,否则内容不好追加也有可能造成资源占用加剧资源消耗。
数据库连接池:在应用程序中,数据库连接池是一个非常重要的资源,单例模式可以确保在应用程序中只有一个数据库连接池实例,避免资源浪费。主要是节省打开或者关闭数据库连接所引起的效率损耗,因为何用单例模式来维护,就可以大大降低这种损耗。
配置文件管理器:在应用程序中,通常只需要一个配置文件管理器来管理应用程序的配置文件,单例模式可以确保在整个应用程序中只有一个配置文件管理器实例。这个是由于配置文件是共享的资源。
缓存系统:在应用程序中,缓存系统是一个重要的组件,单例模式可以确保在整个应用程序中只有一个缓存实例,以提高应用程序的性能。网站在线人数统计:其实就是全局计数器,也就是说所有用户在相同的时刻获取到的在线人数数量都是一致的。
GUI组件:在图形用户界面(GUI)开发中,单例模式可以确保在整个应用程序中只有一个GUI组件实例,以确保用户界面的一致性和稳定性。
public class Singleton { //定义一个私有的静态全局变量来保存该类的唯一实例 private static Singleton singleton; /// <summary> /// 堆代码 duidaima.com /// 构造函数 /// </summary> private Singleton() { //必须是私有的构造函数,这样就可以保证该类无法通过new来创建该类的实例。 //想要使用该类只能通过唯一访问点GetInstance()。 } /// <summary> /// 全局访问点 /// 设置为静态方法则可在外边无需创建该类的实例就可调用该方法 /// </summary> /// <returns></returns> public static Singleton GetInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }上面的代码中,由于构造函数被设置为 private 了,无法再在 Singleton 类的外部使用 new 来实例化一个实例,只能通过访问 GetInstance()来访问 Singleton 类。
public class Singleton { //定义一个私有的静态全局变量来保存该类的唯一实例 private static Singleton singleton; //线程锁 private static readonly object _Object = new object(); /// <summary> /// 构造函数 /// </summary> private Singleton() { //必须是私有的构造函数,这样就可以保证该类无法通过new来创建该类的实例。 //想要使用该类只能通过唯一访问点GetInstance()。 } /// <summary> /// 全局访问点 /// 设置为静态方法则可在外边无需创建该类的实例就可调用该方法 /// </summary> /// <returns></returns> public static Singleton GetInstance() { lock (_Object) { if (singleton == null) { singleton = new Singleton(); } } return singleton; } }相比实例1中可以看到在类中有定义了一个静态的只读对象 _Object(第7行),该对象主要是提供给lock 关键字使用。lock关键字参数必须为基于引用类型的对象,该对象用来定义锁的范围。当多个线程同时进入GetInstance()方法时,由于存在锁机制,当一个线程进入lock代码块时,其余线程会在lock语句的外部等待。
public class Singleton { //定义一个私有的静态全局变量来保存该类的唯一实例 private static Singleton singleton; //线程锁 private static readonly object _Object = new object(); /// <summary> /// 构造函数 /// </summary> private Singleton() { //必须是私有的构造函数,这样就可以保证该类无法通过new来创建该类的实例。 //想要使用该类只能通过唯一访问点GetInstance()。 } /// <summary> /// 全局访问点 /// 设置为静态方法则可在外边无需创建该类的实例就可调用该方法 /// </summary> /// <returns></returns> public static Singleton GetInstance() { if (singleton == null)//第一重 { lock (_Object) { if (singleton == null)//第二重 { singleton = new Singleton(); } } } return singleton; } }相比实例2来看,只是增加了第25行。在多线程中,当第一个线程创建完对象的实例后,singleton变量已经不为null了。之后再访问GetInstance()方法时,将不会再进行lock等待。如果没有这行的情况下,每次多线程同时进入GetInstance()方法时,多余的线程都会进入lock进行等待。这是非常耗费性能的。
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } } }前三个实例在客户端调用:Singleton singletonOne = Singleton.GetInstance();
public sealed class Singleton { //定义一个私有静态的只读的全局变量 private static readonly Singleton singleton = new Singleton(); /// <summary> /// 构造函数 /// </summary> private Singleton() { //必须是私有的构造函数,这样就可以保证该类无法通过new来创建该类的实例。 //想要使用该类只能通过唯一访问点GetInstance()。 } /// <summary> /// 全局访问点 /// 设置为静态方法则可在外边无需创建该类的实例就可调用该方法 /// </summary> /// <returns></returns> public static Singleton GetInstance() { return singleton; } }在c#中使用静态初始化时无需显示地编写线程安全代码,C# 与 CLR 会自动解决前面提到的懒汉式单例类时出现的多线程同步问题。当整个类被加载的时候,就会自行初始化 singleton 这个静态只读变量。而非在第一次调用 GetInstance()时再来实例化单例类的唯一实例,所以这就是一种饿汉式的单例类。