设计模式----单例模式实例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaoxiaovbb/article/details/80102362

单例模式通常分懒汉和饿汉两种模式。

1、懒汉单例模式

         可以理解为懒汉模式创建的类,非常懒,只有在被调用时才会判断自身是否已有对象,如果没有就立即创建自身对象,然后返回。如果已有对象就立即返回。

public Class Single(){
    private static Single intance = null;
    private Single();//私有默认构造器
    public static synchronized Single getIntence(){//添加同步锁,防止多线程同时进入造成多次实例化
         if(intence==null){
        intance = new Single();
        }
       return intance;
    }
}

            优点:调用时才会初始化,避免资源浪费。

            缺点:加了synchronized锁,影响效率 。       


2、饿汉单例模式

        可以理解为饿汉模式创建的类都很饥渴,在类加载的时候就创建对象。

public Class Single(){
    public static Single intance = new Single();//当类加载时就调用自身
    private Single(){};
    public static Single getIntance(){
     return intance;
    }
}

      优点:1、线程安全,在类加载时创建实例不存在在运行过程中,多个线程创建多次实例,避免了多线程同步的情况。

               2、调用时速度快。

      缺点:资源效率不高,如果之后没有用到getinstance()的话,会造成资源浪费。


下面介绍几种单例模式为常用细分类:

       1、懒汉模式不安全(lazy loading)

        严格意义上不是单例模式,这种模式不能在多线程环境下使用。

public Class Single(){
    private static Single instance;
    private Single();
    public static Single getInstance(){  //未加安全锁,大家一起用
      if(instance == null){
         instance = new Single();
      }
      return instance;
    } 
}

      很明显这种方式不适合在多线程下使用。

        下面这几种都适合多线程使用。

       2、双重检验锁/双检锁

       他是懒汉的一种,这种方式采用了双锁机制,在安全下保持高性能。

public Class Single(){
    private static Single instance;
    private Single();
    private static Single getInstance(){
        if(instance == null){
           synchronized(Single.class);
           if(instance == null){
             instance = new Single();
           }
        }
    }
    
}

        可在实例域需要延迟初始化的时候使用。

        3、登记式/静态内部类

        对静态域进行延迟初始化应用这种方式而不用双检锁。

public Class Single(){
     private static class SingleHandler(){
          private static final Single() instance = new Single();
     }
      private Single(){}
      public static final Single getInstance(){//吐槽下 csdn这个编辑器真滴不咋好使
          return SingleHandler.instance;
     }

}

     这种方式就是Single类被加载后,instance不一定被实例化。如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。

         4、枚举

         这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。他不具有懒汉的特性。由于 JDK1.5 之后才加入 enum 特性,在实际工作中,很少用。

            不能通过 reflection attack 来调用私有构造方法。

public enum Single(){
    instance;
    public void method(){
       
    }
}

总结  

         通常,不建议使用懒汉模式不安全和synchronizad懒汉方式,建议使用饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用登记式。如果涉及到反序列化创建对象时,可以尝试使用枚举方式。如果有其他特殊的需求,可以考虑使用双检锁方式。

 

猜你喜欢

转载自blog.csdn.net/xiaoxiaovbb/article/details/80102362
今日推荐