保证一个类仅有一个实例,并提供一个访问它的全局访问点。
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
单例模式作用:解决一个全局使用的类,频繁创建和销毁。拥有对象的唯一性,并保证内存中对象的唯一。可以节省内存,因为单例共用一个实例
优点:
1、减少内存开销,尤其是频繁的创建和销毁实例
2、避免对资源对过多占用。
缺点:
1、没有抽象层,不能继承扩展很难。
2、违背了“单一职责原则”,一个类只重视内部关系,而忽略外部关系。
3、不适用于变化对象。
4、滥用单例会出现一些负面问题,如为节省资源将数据库连接池对象设计为单例,可能会导致共享连接池对象对程序过多而出现连接池溢出。如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这样将导致对象状态丢失。
使用场景:
- 1、要求生产唯一序列号。
- 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
- 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
/// <summary>
/// 写法1.饿汉式(静态常量)(可用,不推荐)
/// 优点:写法简单,类加载时就完成实例化。避免线程同步问题。
/// 缺点:没有延时加载,如果从始至终从未使用过这个实例,则会造成内存的浪费。
/// </summary>
public class Singleton1
{
private static Singleton1 instance = new Singleton1();
private Singleton1() { }//私有化默认构造函数,禁止外部实例化
public static Singleton1 getInstance()
{
return instance;
}
}
/// <summary>
/// 写法2.懒汉式(双重检查)(推荐用)
/// 优点:线程安全;延迟加载;效率较高。
/// </summary>
public class Singleton2
{
private static Singleton2 instance;
private readonly static object lockobj = new object();
private Singleton2() { }//私有化默认构造函数,禁止外部实例化
public static Singleton2 getInstance()
{
if(instance == null)
{
lock (lockobj)
{
if (instance == null)
instance = new Singleton2();
}
}
return instance;
}
}
/// <summary>
/// 写法3.静态内部类(最推荐用)
/// 优点:避免了线程不安全,延迟加载,效率高。
/// </summary>
public class Singleton3
{
private Singleton3() { }//私有化默认构造函数,禁止外部实例化
private static class SingletonInstance
{
private static readonly Singleton3 instance = new Singleton3();
public static Singleton3 Instance
{
get
{
return instance;
}
}
}
public static Singleton3 getInstance()
{
return SingletonInstance.Instance;
}
}