闽公网安备 35020302035485号
缺点:没有接口,扩展困难。
日志系统:在应用程序中,通常只需要一个日志系统,以避免在多个地方创建多个日志对象。这一般是由于共享的日志文件一直处于打开状态,所以只能有一个实例去操作,否则内容不好追加也有可能造成资源占用加剧资源消耗。
数据库连接池:在应用程序中,数据库连接池是一个非常重要的资源,单例模式可以确保在应用程序中只有一个数据库连接池实例,避免资源浪费。主要是节省打开或者关闭数据库连接所引起的效率损耗,因为何用单例模式来维护,就可以大大降低这种损耗。
配置文件管理器:在应用程序中,通常只需要一个配置文件管理器来管理应用程序的配置文件,单例模式可以确保在整个应用程序中只有一个配置文件管理器实例。这个是由于配置文件是共享的资源。
缓存系统:在应用程序中,缓存系统是一个重要的组件,单例模式可以确保在整个应用程序中只有一个缓存实例,以提高应用程序的性能。网站在线人数统计:其实就是全局计数器,也就是说所有用户在相同的时刻获取到的在线人数数量都是一致的。
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()时再来实例化单例类的唯一实例,所以这就是一种饿汉式的单例类。