单例模式
本篇博客将介绍单例模式,单例模式是结构最简单的设计模式,在他的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以确保系统中一个类只有一个实例,而且这个实例可以被外界轻松的访问,从而方便对实例个数进行控制,节约系统资源。
模式分类
创建型设计模式。
模式产生的原因
对于一个软件系统中的某些特殊类来说,只有一个实例很重要。例如,一个系统只能有一个文件系统或者窗口管理器;一个系统只能有一个计时工具或者ID生成器等。如何保证一个类只有一个实例且这个实例要易于被外界访问呢?,一个比较好的解决方案是让类自身负责创建和保存他的唯一实例,并保证不能创建其他实例,他还需要提供一个访问该实例的方法,这就是单例模式的动机。
模式类图
通常,为了防止外部对单例模式进行实例化,我们一般会将单例模式的构造函数设计为private访问等级。
经典代码实现
经典例子:
namespace Singleton.SingletonClassic
{
public class SingletonClassic
{
private static SingletonClassic _instance;
public SingletonClassic GetInstance
{
get
{
if (_instance == null)
{
_instance = new SingletonClassic();
}
return _instance;
}
}
/// <summary>
/// 一般来说,单例模式的构造函数为私有的
/// </summary>
private SingletonClassic()
{
}
}
}
饿汉式单例模式:
namespace Singleton.SingletonClassic
{
public class EagerSingleton
{
private static EagerSingleton _instance = new EagerSingleton();
public EagerSingleton GetInstance()
{
return _instance;
}
private EagerSingleton()
{
}
}
}
懒汉式单例模式:
namespace Singleton.SingletonClassic
{
public class LazySingleton
{
private static LazySingleton _instance;
public LazySingleton GetInstance
{
get
{
if (_instance == null)
{
_instance = new LazySingleton();
}
return _instance;
}
}
private LazySingleton()
{
}
}
}
懒汉式单例模式加双重检查锁定:
namespace Singleton.SingletonClassic
{
public class LazySingleton
{
private static LazySingleton _instance;
//程序运行时创建一个静态只读的辅助对象
private static readonly object syncRoot = new object();
public LazySingleton GetInstance
{
get
{
//第一重判断,先判断实力是否存在,不存在再加锁处理
if (_instance == null)
{
//加锁的程序在某一时刻只允许一个线程访问
lock (syncRoot)
{
//第二重判断
if (_instance == null)
{
_instance = new LazySingleton();
}
}
}
return _instance;
}
}
private LazySingleton()
{
}
}
}
单例模式总结
单例模式的优点:
- 单例模式提供了对唯一实例的受控访问,因为单例类封装了他唯一的实例,所以可以严格控制客户怎么访问他以及何时访问它。
- 由于内存中只存在一个对象,可以节约系统资源。
- 单例模式允许可变数目的实例,这样的单例称之为多例类。
单例模式的缺点:
- 单例类没有抽象层,所以拓展比较困难。
- 单例类的职责过重,在一定程度上违背了单一职责原则。