单例模式-4种实现方式

故事:

帅哥:“我是一个很专一的人,一生只爱一个。”

美女:“怎么证明?”

伪代码

1.饿汉单例模式
public class MyHeart {      private final static MyHeart MY_HEART = new MyHeart();     private MyHeart(){}     public static MyHeart getMyHeart(){         return MY_HEART;     }  } 

优点:随着类的加载而加载,执行效率高,没有线程安全问题

缺点:如果有大量的类都使用单例模式,但是有的类时间情况是不需要立马就使用,这就造成了内存的浪费

2.懒汉单例模式
public class MyHeartLazy {      private static MyHeartLazy MY_HEART = null;      private MyHeartLazy() {     }     public synchronized static MyHeartLazy getMyHeart() {         if (null == MY_HEART) {             MY_HEART = new MyHeartLazy();         }         return MY_HEART;     }  }  /**  *	懒汉模式之双重检查锁(double check lock ----简称DCL)  *	《javab并发编程》提到双重检查的模式现在并不推荐  *  这种写法是因为在无竞争同步的执行速度很慢,以及JVM启动很慢才出现的这种写法,  *  现在无论是JVM还是synchronized关键字都有了优化。  *  所以上面的写法已经完全满足了现实的要求  *  */   class MyHeartLazyDoubleCheck {     private static volatile MyHeartLazyDoubleCheck MY_HEART_DCL = null;      private MyHeartLazyDoubleCheck() {     }          public static MyHeartLazyDoubleCheck getMyHeart() {         if (MY_HEART_DCL == null) {             synchronized (MyHeartLazyDoubleCheck.class) {                 if (MY_HEART_DCL == null) {                     MY_HEART_DCL = new MyHeartLazyDoubleCheck();                 }                     return MY_HEART_DCL;             }         }         return MY_HEART_DCL;     } }  

优点:节省了内存,只有在需要的时候才会创建单例

缺点:存在线程安全问题,需要用到锁

3.注册式单例
public class MyHeartRegister {      private final static Map<String, MyHeartRegister> MY_HEART = new HashMap<>();      private MyHeartRegister() {      }      public static synchronized MyHeartRegister getMyHeart() {         if (MY_HEART.get("myheart") == null) {             MY_HEART.put("myheart", new MyHeartRegister());         }         return MY_HEART.get("myheart");     } } 

优缺点和懒汉模式差不多

4.枚举单例
public enum MyHeartEnum {      MY_HEART;      public void showMyHeart(){         System.out.println("我是很专一的,只有一个对象");     }  } 

在《effective Java》中,作者强烈推荐使用该种写法。

反射是可以拿到私有构造方法的,而序列化和反序列化也会生成新的实例,从而破环单例模式。而枚举单例模式可以有效防止这两种攻击。需要注意的是,如果我们的单例需要被继承,则不推荐使用枚举类型模式。

测试枚举单例

/**  * 枚举单例模式测试  * @author 康康的远方  * @date 2021/3/28  */ public class SingleTest {     public static void main(String[] args) {          MyHeartEnum myHeart = MyHeartEnum.MY_HEART;         MyHeartEnum myHeart2 = MyHeartEnum.MY_HEART;         myHeart.showMyHeart();         System.out.println(myHeart==myHeart2); //返回true     } } 

版权声明:玥玥 发表于 2021-03-30 4:01:31。
转载请注明:单例模式-4种实现方式 | 女黑客导航