单例模式也就是保证一个类只有一个实例,并提供一个全局访问点。单例设计模式解决问题:
1、在内存中只有一个对象,节省内存空间;
2、避免频繁的创建销毁对象,可以提高性能;
3、避免对共享资源的多重占用,简化访问,为整个系统提供一个全局访问点。
使用场景:单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此以下几种情况下适用单例设计模式:
1.需要频繁实例化然后销毁的对象。
2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3.频繁访问数据库或文件的对象。
实现步骤:
(1)私有化构造函数,使其不能在类的外部通过new关键字随意实例化该类对象。
(2)在该类内部定义一个私有的静态字段。【不会释放,并且在第一次使用这个类时被初始化,而且只初始化一次】。
(3)对外提供一个公开的静态方法提供实例。
懒汉式实现单例
外部第一次调用CreateInstance方法,对象被创建。
private DbProxyHandler()//private 避免外部创建 { } //volatile 可以保证运行过程中值不会被重复修改 private static volatile DbProxyHandler _SingletonDbProxyHandler = null; private static object slock = new object(); /// <summary> /// /// </summary> /// <returns></returns> public static DbProxyHandler CreateInstance() { if (_SingletonDbProxyHandler == null)//保证对象初始化之后,不在去等待锁 { lock (slock)//保证只有一个线程进去 { if (_SingletonDbProxyHandler == null)//保证只被实例化一次 _SingletonDbProxyHandler = new DbProxyHandler(); } } return _SingletonDbProxyHandler; }//懒汉式 调用了方法才去构造
饿汉式——使用静态构造函数
静态构造函数:由CLR保证,程序第一次使用这个类型前被调用,且只调用一次。
#region 饿汉式---使用静态构造函数实现单例 /// <summary> /// 构造函数耗时耗资源 /// </summary> private DbProxyHandler() { Console.WriteLine("DbProxyHandler 被构造"); } /// <summary> /// 静态构造函数:由CLR保证,程序第一次使用这个类型前被调用,且只调用一次 /// /// 写日志功能的文件夹检测 /// XML配置文件 /// </summary> static DbProxyHandler() { _SingletonSecond = new DbProxyHandler(); } private static DbProxyHandler _SingletonSecond = null; public static DbProxyHandler CreateInstance() { return _SingletonSecond; }//饿汉式 只要使用类就会被构造 #endregion
如下测试代码及结果如下:
public void TestSingleton() { Console.WriteLine("--------使用DbProxyHandler类Start------------"); var s= DbProxyHandler.connStr; //:并没有调用CreateInstance方法,只是使用了DbProxyHandler类 Console.WriteLine("--------使用DbProxyHandler类End------------"); Console.WriteLine("------调用CreateInstance方法--------------"); DbProxyHandler dbProxyHandler1 = DbProxyHandler.CreateInstance(); //:调用CreateInstance方法 Console.WriteLine("------调用CreateInstance方法End--------------"); }
注:从上面的测试可以看出,饿汉式静态构造函数实现单例,在第一次使用DbProxyHandler类时,对象就已经被构造,调用DbProxyHandler.CreateInstance()方法时,
没有二次创建对象,而是直接返回了对象
饿汉式——使用静态字段
静态字段:在第一次使用这个类之前,由CLR保证,初始化且只初始化一次
#region 饿汉式使用静态字段 private DbProxyHandler() { Console.WriteLine(" 饿汉式使用静态字段实现单例模式被创建"); } /// <summary> /// 静态字段:在第一次使用这个类之前,由CLR保证,初始化且只初始化一次 /// </summary> private static DbProxyHandler _DbProxyHandler = new DbProxyHandler();//打印个日志 public static DbProxyHandler CreateInstance() { return _DbProxyHandler; }//饿汉式 只要使用类就会被构造 #endregion
如下测试代码及结果如下:
public void TestSingleton() { Console.WriteLine("--------使用DbProxyHandler类Start------------"); var s= DbProxyHandler.connStr; //:并没有调用CreateInstance方法,只是使用了DbProxyHandler类 Console.WriteLine("--------使用DbProxyHandler类End------------"); Console.WriteLine("------调用CreateInstance方法--------------"); DbProxyHandler dbProxyHandler1 = DbProxyHandler.CreateInstance(); //:调用CreateInstance方法 Console.WriteLine("------调用CreateInstance方法End--------------"); }
注:饿汉式静态字段实现单例,在第一次使用DbProxyHandler类时,对象就已经被构造,调用DbProxyHandler.CreateInstance()方法时,
没有二次创建对象,而是直接返回了对象。
总结:
1、饿汉式 :第一时间创建实例,类加载就马上创建
2、懒汉式 :需要才创建实例,延迟加载
3、单例模式会长期持有一个对象,不会释放 ,普通实例使用完后释放
4、单例可以只构造一次,提升性能(如果构造函数耗性能)