定义(单例模式又称单件模式)
单件模式(Singleton Pattern)要求一个类有且仅有一个实例,并且提供了一个全局的访问点,在同一时刻只能被一个线程所访问。
- 单件类只能有一个实例。
- 单件类必须自身创建唯一实例。
- 单件类必须给所有其它对象提供唯一实例。
C#例子
/// <summary>
/// 单件模式实现方式:简单线程安全。
/// </summary>
public sealed class Singletion
{
//私有构造函数,防止通过new实例化对象
private Singletion() {
}
//定义一个静态变量来保存类的实例
private static Singletion _instance;
//定义一个标识确保线程同步
private static readonly object _lock = new object();
//定义公有静态方法,获取实例,并加入判断,保证实例只被创建一次
public static Singletion GetInstance() {
if (_instance == null) {
//锁,多线程时,保证实例只被创建一次
lock (_lock)
{
if (_instance == null)
{
_instance = new Singletion();
}
}
}
return _instance;
}
public string GetName() {
return "我是单例模式";
}
}
static void Main(string[] args)
{
var singletion = Singletion.GetInstance();
Console.WriteLine( singletion.GetName());
Console.ReadLine();
}
单件模式参与者:
- Singleton: 被调用的单件对象;在单件模式中,通常由Instance()或GetInstance()方法负责对象的创建,该方法应保证每个需要(单件)对象的客户端均能访问。
单件模式实现要点
- 单件类有一个私有的无参构造函数,防止被其他类实例化。
- 单件类不能被继承,使用sealed修饰。
- 单件类使用静态的变量保存单实例的引用。
- 单件类使用公有静态方法获取单一实例的引用,如果实例为null即创建一个。
单件模式使用注意点
- 不要使用单例模式存取全局变量。这违背了单例模式的用意,最好放到对应类的静态成员中。
- 不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能及时释放连接。Singleton模式由于使用静态成员存储类实例,所以可能会造成资源无法及时释放。
单件模式适用情形
- 当类只能有一个实例而且客户可以从一个众所周知的访问点访问时;
- 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能适用一个扩展的实例时。
单件模式特点
- 实例控制:Singleton会阻止其他对象实例化其自己的Singleton对象的副本,从而确保所有对象都访问唯一实例;
- 额外的开销:虽然很小,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销;
- 可能的开发混淆:使用Singleton对象时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类;
- 对象的生存期问题:Singleton不能解决删除单个对象的问题。在提供内存管理的语言中(如.Net Framework的语言),只有Singleton类能够导致实例被取消分配,因为它包含该对象实例的私有引用。在某些语言中(如C++),其他类可以删除对象实例,但这样会导致Singleton类中出现悬浮引用。
其他
源码地址
其他设计模式