单例模式
前言
确保一个类在任何情况下都只会存在一个实例。
一、概念
确保一个类在任何情况下都只会存在一个实例。并提供一个全局的访问点。
二、应用场景
- 需要频繁创建实例的一些类,使用单例可以减低系统的内存压力,减少GC。
- 创建实例时占用资源较多,或者耗时长,并且经常使用。
- 频繁访问数据库或文件的对象。
- 对于一些仅限于单线程操作的场景,多线程可能会导致实例过多。
三、代码
1.通用代码
代码如下(示例):
/// <summary>
/// 简单单例
/// </summary>
public class SimpleSingleton
{
private static SimpleSingleton simpleSingletonModel = null;
private SimpleSingleton()
{
}
public static SimpleSingleton GetSimpleSingleton()
{
var thread = Thread.CurrentThread;
Console.WriteLine($"GetSimpleSingleton------Thread id:{thread.ManagedThreadId},Thread Name:{thread.Name}");
if (simpleSingletonModel == null)
{
simpleSingletonModel = new SimpleSingleton();
}
return simpleSingletonModel;
}
}
2.线程安全单例代码
说明:使用双if+lock来保证单例线程安全,lock保证每次都只能有一个线程进入并创建对象,并且因为创建对象时多个进入锁的线程所以进入锁后仍需要添加判断。
/// <summary>
/// 线程安全单例
/// </summary>
public class ThreadSafeDemo
{
private static ThreadSafeDemo demo = null;
private static readonly object _lock = new object();
private ThreadSafeDemo()
{
Console.WriteLine("内部调用的构造函数");
}
public static ThreadSafeDemo GetThreadDemo()
{
if (demo == null)
{
Console.WriteLine("Demo is null");
lock (_lock)
{
Console.WriteLine("In the Lock");
if (demo == null)
{
demo = new ThreadSafeDemo();
Console.WriteLine("Create ThreadSafeObject");
}
}
}
else
{
Console.WriteLine("Demo is not null");
}
var thread = Thread.CurrentThread;
Console.WriteLine($"GetSimpleSingleton------Thread id:{thread.ManagedThreadId},Thread Name:{thread.Name}");
return demo;
}
}
总结
优点
- 单例可以保证内存里只有一个实例,减少了内存的开销
- 避免对资源的多重占用
- 设置全局访问点,可以优化和共享资源的访问。
缺点
- 没有接口,扩展困难,如果进行扩展则需要修改原来的代码。
- 并发测试中,单例模式不利于代码调试,调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
- 单例模式的功能代码通常写在一个类中,如果功能设计不合理,很容易违背单一职责原则。