设计模式--01单例模式

设计模式–01单例模式

引言:
经过一段时间的学习设计模式,自己总结一下,以前经常看博客中的大牛们写的,但是最终发现,自己不动手去写,很快就会忘记,最终决定自己写一写博客,一遍加深自己的理解。

  1. 什么是设计模式?
    设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。

  2. 写设计模式的目的?
    使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性,松耦合等。

  3. 单例模式
    一.什么是单例模式?

通俗的讲:一个类一个实例一种实现方法。
官方的定义:确保一个类只有一个实例,并提供一个全局访问点**

二.为什么会有单例模式呢?它在什么情况下使用呢?**

例如:电脑的任务管理器,它就是一个单例模式,同一时间只允许一个实例对其进行操作。自然在软件设计领域必须有这样的解决方案(因为软件设计也是现实生活中的抽象),所以也就有了单例模式。

三.剖析单例模式的实现思路?
首先我会提问几个问题:
1.如何实现一个类只能有一个实例? 定义一个私有静态变量来保存实例,定义一个私有的构造函数,使其不能实例化,用private【保证不能创建该类的实例】
2.如何提供一个全局的访问站点? 定义一个共有的方法提供一个全局访问站点
3.如何能够在多线程的情况下只有一个实例? 定义静态私有变量,为什么要定义一个静态的呢?每个线程都有自己的线程栈,【定义为静态主要是为了在多线程确保类有一个实例】
弄明白这几个问题,那么写一个单例模式就Soeasy。

四.代码实现

一.单线程的情况

 public class SingletonMode
   {
 	  //私有化,静态变量确保只有一个实例
         private static SingletonMode uniqueInstance;
       //私有的构造函数,私有方法SingletonMode()来防止外界使用new来创建新的实例
         private SingletonMode()
          {
          }
          //提供一个全局的访问点
         public static SingletonMode GetInstance()
         {
            if (uniqueInstance == null)
            {
                uniqueInstance = new SingletonMode();
             }
            return uniqueInstance;
        }
   }

上述代码只适合单线程的情况,如果是多线程的情况下,同时会得到多个uniqueInstance实例,如果两个线程同时运行GetInstance方法时,且uniqueInstance == null同时为true的话,那就违背单例模式的初衷啦,对于多线程的解决方案,就是在同一个时间只有一个线程GetInstance运行就好啦,这就是线程同步的问题,具体的代码如下:
二.多线程:

 public class SingletonMode
   {
         //私有化,静态变量确保只有一个实例
	 private static SingletonMode uniqueInstance;
	 
	// 定义一个标识确保线程同步
	private static readonly object obj = new object();
	
	 //私有的构造函数,私有方法SingletonMode()来防止外界使用new来创建新的实例
	  private SingletonMode()
          {
          }
          
          //提供一个全局的访问点
	  public static SingletonMode GetInstance()
	      {
	      // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
            // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
            // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
 	       lock (obj)
	          {
   	         if (uniqueInstance == null)
    	        {
         	       uniqueInstance = new SingletonMode();
      	       }
       	     return uniqueInstance;
     	     }
  	     }
   } 

上面这种解决方案确实可以解决多线程的问题,但是上面代码对于每个线程都会对线程辅助对象locker加锁之后再判断实例是否存在,对于这个操作完全没有必要的,因为当第一个线程创建了该类的实例之后,后面的线程此时只需要直接判断(uniqueInstancenull)为假,此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销,损失了性能,为了改进上面实现方式的缺陷,我们只需要在lock语句前面加一句(uniqueInstancenull)的判断就可以避免锁所增加的额外开销,这种实现方式我们就叫它 “双重锁定”,下面具体看看实现代码的:

public class SingletonMode
   {
	  //私有化,静态变量确保只有一个实例
        private static SingletonMode uniqueInstance;
        
	// 定义一个标识确保线程同步
	private static readonly object obj = new object();
	
	 //私有的构造函数,私有方法SingletonMode()来防止外界使用new来创建新的实例
	  private SingletonMode()
          {
          }
         / /提供一个全局的访问点
	  public static SingletonMode GetInstance()
       {
            // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
            // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
            // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
            // 双重锁定只需要一句判断就可以了
	       if(uniqueInstance  == null)
	       {
		   lock (obj)
      	     {
       	      if (uniqueInstance == null)
     	        {
        	         uniqueInstance = new SingletonMode();
       	       }
    	         return uniqueInstance;
           	}
        }
      }
   } 
 

你可能感兴趣的:(设计模式)