C# 设计模式巩固 - 单例模式
前言
设计模式的文章很多,所以此文章只是为了巩固一下自己的基础,说的不详细请见谅。
介绍 - 单例模式
官方定义:确保一个类只有一个实例,并提供一个全局访问点。
通俗定义:就是一个类只有一个单个实例。(也没啥区别)
实现
如何保证一个类只有一个实例呢?
1. 首先一个类是如何创建实例的? - 通过构造函数
2. 如何保证只创建一个呢? - 构造函数只执行一次
3. 如何保证构造函数只执行一次呢? - 访问外部类无权访问
4. 如何让访问外部类无权访问? - 私有方法
问题解决,上代码:
/// <summary> /// 单例类 /// </summary> public class Singleton { /// <summary> /// 私有构造函数 /// </summary> private Singleton() { } /// <summary> /// 单例字段 /// </summary> private static Singleton _instance; /// <summary> /// 单例对象 /// </summary> public static Singleton Instance { get { if (_instance == null) _instance = new Singleton(); return _instance; } } /// <summary> /// 输出 /// </summary> public void WriteLine() { Console.WriteLine("哈希Code : " + this.GetHashCode()); } }
测试输出 HashCode :
class Program { static void Main(string[] args) { Singleton.Instance.WriteLine(); Singleton.Instance.WriteLine(); Singleton.Instance.WriteLine(); Console.Read(); } }
结果:
这样就结束了吗? -(身为C#老鸟的我还要考虑下线程安全的问题,考虑并发的情况)
我们需要构建一个并发的情形及多条线程同时创建对象,下面我就用简单粗暴的方法,需要对单例进行修改:
/// <summary> /// 单例对象 /// </summary> public static Singleton Instance { get { if (_instance == null) { Thread.Sleep(1); _instance = new Singleton(); } return _instance; } }
调用测试:
class Program { static void Main(string[] args) { //线程1 Thread thread1 = new Thread(new ThreadStart(() => { Singleton.Instance.WriteLine(); })); //线程2 Thread thread2 = new Thread(new ThreadStart(() => { Singleton.Instance.WriteLine(); })); //线程3 Thread thread3 = new Thread(new ThreadStart(() => { Singleton.Instance.WriteLine(); })); thread1.Start(); thread2.Start(); thread3.Start(); Console.Read(); } }
输出结果:
所以我们要对代码进行改进(加锁):
/// <summary> /// 单例类 /// </summary> public class Singleton { /// <summary> /// 锁 /// </summary> private static object locker = new object(); /// <summary> /// 私有构造函数 /// </summary> private Singleton() { } /// <summary> /// 单例字段 /// </summary> private static Singleton _instance; /// <summary> /// 单例对象 /// </summary> public static Singleton Instance { get { lock (locker) { if (_instance == null) { Thread.Sleep(1); _instance = new Singleton(); } } return _instance; } } /// <summary> /// 输出 /// </summary> public void WriteLine() { Console.WriteLine("哈希Code : " + this.GetHashCode()); } }
测试结果:
解决!
锁是个好东西但是要慎用,它是很耗资源的。所以还需要对代码进行改进,看代码我们知道只有 _instance 为 null 时才需要考虑并发加锁,所以我们再次改进:
/// <summary> /// 单例类 /// </summary> public class Singleton { /// <summary> /// 锁 /// </summary> private static object locker = new object(); /// <summary> /// 私有构造函数 /// </summary> private Singleton() { } /// <summary> /// 单例字段 /// </summary> private static Singleton _instance; /// <summary> /// 单例对象 /// </summary> public static Singleton Instance { get { if(_instance == null) { lock (locker) { if (_instance == null) { Thread.Sleep(1); _instance = new Singleton(); } } } return _instance; } } /// <summary> /// 输出 /// </summary> public void WriteLine() { Console.WriteLine("哈希Code : " + this.GetHashCode()); } }
欢迎批评指正!转载请注明出处:http://www.cnblogs.com/xinwang/p/6294784.html