一、单例模式的概念及种类
单例模式的概念:通过单例模式的方法创建的类在当前进程中只有一个实例,简单来说单例模式就是一个类只创建一个对象,同时对外提供这个对象的访问接口
单例模式的分类:懒汉式单例模式和饿汉式单例模式
二、单例模式的实现及优化
namespace SingletonPattern
{
//单例模式:一个类只创建一个对象,这个类中只做两件事情,创建对象,提供一个静态方法来实现这个对象的使用 静态类中的所有内容都是静态的
/// <summary>
/// 饿汉式单例模式创建:在类加载的时候就会创建对象
/// </summary>
class HungrySingletion
{
//构造函数私有化,就不能在这个类的外部创建对象
private HungrySingletion()
{
}
//因为静态方法中不能访问非静态成员变量,所以这个对象创建也是静态的
private static HungrySingletion instance = new HungrySingletion();
//创建一个公有的静态函数来实现对这个单例的访问(对外提供一个访问的接口)
public static HungrySingletion GetInstance()
{
return instance;
}
}
/// <summary>
/// 懒汉式单例模式:在类加载的时候不会创建对象,只有在类首次使用的时候才创建对象
/// </summary>
class LazySingletion
{
//构造函数私有化,就不能在这个类的外部创建对象
private LazySingletion()
{
}
//因为静态方法中不能访问非静态成员变量,所以这个对象创建也是静态的
private static LazySingletion instance; //这里只是声明了对象的定义,但是并没有创建对象
private static object sybcRoot = new object(); //创建一个锁
//创建一个公有的静态函数来实现对这个单例的访问 首次使用的时候直接就调用这个方法就可以
public static LazySingletion GetInstance()
{
//第一次判断,如果instance的值不为null,那么则不需要抢占锁,直接返回对象
if (instance == null) //需要加一个判定条件确定只创建一个对象,且每次所调用的对象都是一个对象
{
lock (sybcRoot)
{
instance = new LazySingletion();
}
}
return instance;
}
}
/// <summary>
/// 双重检查锁模式:在饿汉式单例模式中通过上锁的办法确保了在多线程中使用单例模式的安全,
/// 但是同时每次都需要判断锁的条件会造成性能消耗,因此产生了双重检查锁模式;双重检查锁模式多线程的时候可能会出现空引用的问题
/// </summary>
class DoubleCheckLockSingleton
{
private DoubleCheckLockSingleton()
{
}
//volatile关键字的作用就是保证可见性和有序性
//volatile关键字解决的是双重检查锁模式多线程的时候可能会出现空引用的问题具体需要看并发的内容
//可以简单理解为就是对象分配好内存了,但是还没有进行初始化,这个时候另一个线程就有可能返回一个不完整的对象
private static volatile DoubleCheckLockSingleton instance;
private static readonly object sybcRoot = new object();
public static DoubleCheckLockSingleton GetInstance()
{
//第一次判断如果instance的值不为null,不需要抢占锁,直接返回对象,提升效率
if (instance == null)
{
lock (sybcRoot)
{
//二次判断
if (instance == null)
{
instance = new DoubleCheckLockSingleton();
}
}
}
return instance;
}
}
/// <summary>
/// 静态内部类方式:在没有加任何锁的情况下,保证了多线程的安全,且没有任何性能影响和空间的浪费
/// </summary>
class StaticClassSingleton
{
private StaticClassSingleton()
{
}
//定义一个静态内部类
private static class SingletonHolder
{
//在内部类中声明并初始化外部类的对象
internal static StaticClassSingleton instance = new StaticClassSingleton();
}
//提供公共的访问方式
public static StaticClassSingleton GetInstance()
{
return SingletonHolder.instance;
}
}
class EnumSingletonClass
{
/// <summary>
/// 枚举类单例模式,属于饿汉式方法,不考虑浪费内存空间的话首选就是这个
/// </summary>
public enum EnumSingleton
{
INSTANCE,
}
}
}
三、总结
懒汉式单例模式的使用场景:线程池、数据库链接等
饿汉式单例模式的使用场景:资源加载、线程池等