设计模式__单例模式

单例模式:确保一个类只有一个实例,而且自行实例化。

单例模式是我们用的最多的模式,也应该最先了解的模式。它的实现有很多种,我们一一道来,置于使用场景我们在优点中一起分析。在实现单例之前我们首先需要注意以下几点:

    1. 构造器私有化-------一个项目只需要一个该类实例,确保不能随便new出一个新实例;

    2. 建一个静态方法返回单例类对象--------该项目中可以获得这个类实例的唯一方法;

    3. 确保项目中只有一个实例,尤其多线程情况下;

    4. 防止单例模式被反射或者反序列化时重新创建对象。

饿汉式:

public class Singleton{
    //静态实例对象
    private static Singleton instance=new Singleton();
    //私有化构造器
    private Singleton(){}
    
    //公有的静态方法,暴露给使用者
    public static Singleton getInstance(){
      return instance();
    }
    
}

其实饿汉式是非常不错的单例模式,保证了一个项目中多线程情况下仍是只有一个实例。一个小缺点是静态中直接实力化,如果没用这个类,那就浪费资源了。

懒汉式:

public class Singleton{
   //申明成员变量
   private Singleton instance;
   //私有化构造器
   private Singleton(){}
 
   public static synchronized Singleton getInstance(){
     if(instance==null){
        instance=new Singleton();
     }
     return instance;
   }

}

懒汉式最大的区别就是使用者调用暴露的静态方法时,才会实力化该类。synchronized确保了实例只有一个,但是太耗费资源。每次获取该实例都会进行同步。所以有了双重检索单例

Double check Lock (双重检索机制)-------------使用最多的单例:

public class Singleton(){
  
  //使用volatile 避免处理器指令重排
  private volatile static Singleton instance = null;
  //私有化构造器
  private Singleton(){}

  public static Singleton getInstance(){
    if(instance == null){
      synchronized(Singleton.class){
         if(instance == null){
           instance =new Singleton();
        }
      }
    }
    return instance;
  }  

}

作为最常用的单例模式,我们需要详细讲解一下。

第一点:synchronized 锁的是 Singleton 的 class对象;

第二点:synchronized 中的判空,如果两个线程同时获得锁(前提是这个类一定还没实例化),这样的情况下不判空就会两个线程                实例化两次;

第三点:volatile 在JDK 1.5后具体化了这个关键字,它在这的用处是使得JVM不能指令重排。

              因为:instance =new Singleton(); 这条语句在JVM操作的时候其实是分三步执行的(JVM的相关知识,这两天也会更,                            可以关注一下,不迷路,哈哈哈!!!)。指令大概是:

                        ( 一 )  给Singleton对象分配内存;

                        ( 二 )  调用构造器,初始化该实例;

                        ( 三 )  将instance  指向该对象;

              一般情况,指令顺序是这三步。但是,CPU和JVM会对指令顺序优化,而做指令重排。那么,执行顺序可能就是步奏

              1 -  3  -  2。这样的话如果线程A 执行到第三步,第二步没执行呢,切换到B线程。B线程判断 instance 不为空,但是这                个指向的对象还没实力化,这就会出现问题。这就是volatile的作用。

静态类模式:

public class Singleton{
   //私有化构造器
   private Singleton(){}
   
   //使用静态内部类
   private static class SingletonHodler{
     private static final Singleton instance = new Singleton();
   }

   public static getInstence(){
     return SingletonHolder.instance;
   }

}

使用静态内部类实现了唯一实例化,防止了多线程,推荐使用。

枚举单例:

public enum Singleton{
  INSTANCE;
}

枚举最大的优点就是: 可以防止反射和反序列化,确点性能差;

其他类如果想反序列化加入如下方法:

private Object readResolve() throws ObjectStreamException{
  return instance;
}

单例的优点: 

    1.  单例模式只会有一个实例,减少了内存开支,尤其创建频繁的类;

    2.  读取配置这种情况,可以直接缓存在单例中,减速开支;

    3.  减少了多重占用,例如一个写操作,避免了一个资源被多个对象操作;

    4.  单例可以作为全局的访问点,作为一个共享资源。

缺点:

    1.  单例模式扩展困难,违背了对修改关闭;

    2.  如果持有Context,会造成内存泄露,所以可以用ApplicationContext;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值