zoukankan      html  css  js  c++  java
  • 设计模式

    单例模式

    含义

    保证一类仅有一个实例,并提供一个访问它的全局访问点

    优缺点

    • 优点:
      • 确保所有对象都访问一个实例
      • 节省内存,避免频繁地创建、销毁对象
      • 避免对共享资源的多重占用
    • 缺点:
      • 违背了"单一职责原则"
      • 可扩展性差

    实现过程

    1. 保证单一实例:创建private static类型的对象instance,其为空时才new实例化创建
    2. 全局访问点:创建public类GetInstance()方法用于全局访问instance,并担当检测、new instance的责任

    概念图

    代码实现

    //单例类:
    class Singleton
    {
    	//私有化的构造函数
        private Singleton() { Console.WriteLine("This is a SingleObject"); }
    
    	//单一的实例  
        private static Singleton instance;  	   
     
    	//全局访问点
        public  static Singleton GetInstance()
        {
    		//如果实例为空,则new一个新实例
            if (instance == null)
            {
                instance = new Singleton();
                Console.WriteLine("Create a new Instance");
            }
            else
            {
                Console.WriteLine("Get a Instance");                           
            }
            return instance;
        }
    }
    
    //测试类:
    class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 =  Singleton.GetInstance2();
            Singleton s2 =  Singleton.GetInstance2();
    
    		/* OUT:
    		 This is a SingleObject
    		 Create a new Instance
    		 Get a Instance
    		*/
        }
    }
    

    单例模式分类

    根据new关键字实例化单例的先后顺序,可把单例模式分为饿汉式单例、懒汉式单例

    饿汉式

    • 含义:开始时就实例化instance
    • 优点:线程安全(因为instance是static类型)
    • 缺点:不管是否使用对象,开始时就实例化并占用了空间。即空间换时间
    //饿汉式:开始时就实例化instance
    public class Singleton 
    {  
    	private Singleton (){} 
        private static Singleton instance = new Singleton();  
         
        public static Singleton getInstance() 
    	{  
        	return instance;  
        }  
    }
    

    懒汉式

    • 含义:需要时才实例化instance
    • 优点:资源利用率高。即时间换空间
    • 缺点:多线程下存在隐患
    //懒汉式:需要时才实例化instance
    public class Singleton 
    {   
    	private Singleton (){} 
        private static Singleton instance;  
         
        public static Singleton getInstance() 
    	{  
        	if (instance == null) 
            	instance = new Singleton();  
        	return instance;  
        }  
    }
    

    多线程中的单例

    在上述懒汉式单例中,若多个线程同时进行到if (instance == null),会全部检测通过,最终造成多线程下创建了多个实例,即 多线程不安全。因此需要对多线程下的单例模式进行调整,使用 lock机制实现线程安全

    //饿汉式 + 线程安全 + 单锁
    class Singleton
    {
        private Singleton() {}
        private static Singleton instance;       
      	
    	//静态只读对象用于辅助实现lock
        private static readonly object locker = new object();
    
        public static Singleton GetInstance()
        {
    		//lock机制:确保一个线程位于该临界区时,其他线程不可再进入,直至当前线程访问完毕
            lock (locker)
            {
                if (instance == null)
                    instance = new Singleton();
            }
            return instance;
        }
    }
    

    虽然加了lock锁实现了懒汉模式下的线程安全,但我们不难发现一个问题:若已经存在instance实例,在执行GetInstance()时还有必要lock{}吗?显然不需要,lock的使用必然是消耗一定空间的,因此为了节省lock的空间,采用更优解法:双重锁定(Double-Check-Locking)

    //饿汉式 + 线程安全 + 双锁
    class Singleton
    {
        private Singleton() {}
        private static Singleton instance;       
      	
    	//静态只读对象用于辅助实现lock
        private static readonly object locker = new object();
    
        public static Singleton GetInstance()
        {
    		//首次检验:是否需要加锁
    		if(instance == null)
    		{
    			//为当前线程加锁
    	        lock (locker)
    	        {
    				//再次检验:避免当前线程实例化instance后,下一个线程再次实例
    	            if (instance == null)
    	                instance = new Singleton();
    	        }
    	        return instance;
    		}
        }
    }
    

    参考

  • 相关阅读:
    codevs 3657 括号序列
    洛谷P1962 斐波那契数列
    Black Rock shooter
    codevs 2596 售货员的难题
    51Nod-1154 回文串划分
    UVA
    POJ3321[苹果树] 树状数组/线段树 + dfs序
    Hdu 4578 Transformation (线段树 分类分析)
    786B
    438D
  • 原文地址:https://www.cnblogs.com/SouthBegonia/p/11958875.html
Copyright © 2011-2022 走看看