单例模式

单例模式

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

为什么要使用单例模式:某个类的对象在整个项目是唯一的,它不能也没必要被实例化多次,比如窗口管理器、皮肤加载器等等。这就催生出了如下的现实需求:如何确保某个类只有一个实例。即要使用单例模式。

单例模式有以下特点:

  • 单例类只可有一个实例
  • 单例类必须自己创建自己这唯一的实例,即构造方法私有,外部类不能new来实例化它
  • 单例类必须给所有其他对象提供这一实例的方法,并且开放
    单例模式结构图


    注意:Singleton() 构造方法是私有,GetInstance()是一个静态的方法,主要负责创建自己的唯一实例。
    单例模式创建有两种形式:
  • 饿汉模式
class Singleton
{
	private static final Singleton s = new Singleton(); //final s终生指向这个new Single()

	private Singleton(){} //私有,这就堵死外界利用new创建此类实例的可能
	public static Singleton GetInstance()
	{
		return s;
	}
}
  • 饿汉模式弊端:每个对象在没有使用之前就已经初始化了。这就可能带来潜在的性能问题:如果这个对象很大呢?没有使用这个对象之前,就把它加载到了内存中去是一种巨大的浪费。因此引出下面另外一个模式
  • 懒汉式 (延迟加载)
     
    class Singleton
    {
     private static Singleton s = null;
     private Singleton(){}
     public static  Singleton GetInstance()
     {
     
        if(s==null)
         //--->A;
          //--->B;
          //---->C; 这里应该会出现同步问题!会创建多个实例
         s = new Singleton();
       }
      }
      return s;
     }
    }
    改进版:加上锁
     
    class Singleton
    {
     private static Singleton
     s = null;
     private Singleton(){}
    
    
     public static  Singleton GetInstance()
     {
      
       synchronized(Singleton.class)   //使得最先进入的那个线程创建,以后的在进入是就不能实例化
    每次进来都要判断一次是不是效率很低?
       {
        if(s==null)
         //--->A;
          //--->B;
          //---->C;
         s = new Singleton();
       
      }
      return s;
     }
    }
    这时,我们可以利用双重锁定
     
    class Singleton
    {
     private static Singleton s = null;
     private Singleton(){}
     public static  Singleton GetInstance()
     {
      if(s==null) <执行到第三个就不用上锁了>
      {
              // A 锁定后,刚创建实例时,此时B线程已经运行到这儿,A给资源B后
       synchronized(Singleton.class)
       {
        if(s==null)   //B又判断一次,此时已经实例化,B不会new了。
         s = new Singleton();
       }
      }
      return s;
     }
    }

    看似完美,但是还会有个缺陷的,例如A线程在执行到s = new Singleton();实例化时后,因为初始化是比较耗费时间的,但是这个对象的地址其实已经存在了。此时刚好B线程执行到第一个if(s==null) ; 判断不为null时就直接返回S,此时会得到一个还没有完全初始化的对象! 
  • 但往往面试时候提到饿汉式的双重锁定就足够了,不用深入探究吧!

    注意:
    单例模式类似于Math实用类的采用私有化避免实例化,但是实用类只提供一些静态方法或者静态属性让我们使用,而单例类是有状态的,另外,实用类不能用于继承多态,而单例虽然唯一,却是可以继承的。实用类只不过是一些方法属性的集合,而单例却是唯一的对象实例。
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值