最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA破壞單例模式的方式以及避免方法

 更新時間:2020年06月16日 11:32:04   作者:宋者為王  
這篇文章主要介紹了JAVA破壞單例模式的方式以及避免方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下

      單例模式,大家恐怕再熟悉不過了,其作用與實現(xiàn)方式有多種,這里就不啰嗦了。但是,咱們在使用這些方式實現(xiàn)單例模式時,程序中就真的會只有一個實例嗎?

      聰明的你看到這樣的問話,一定猜到了答案是NO。這里筆者就不賣關(guān)子了,開門見山吧!實際上,在有些場景下,如果程序處理不當(dāng),會無情地破壞掉單例模式,導(dǎo)致程序中出現(xiàn)多個實例對象。

      下面筆者介紹筆者已知的三種破壞單例模式的方式以及避免方法。

1、反射對單例模式的破壞

      我們先通過一個例子,來直觀感受一下

    (1)案例

  DCL實現(xiàn)的單例模式:

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

測試代碼:

public class SingletonDemo {

  public static void main(String[] args){
    Singleton singleton = Singleton.getInstance();
    try {
      Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
      constructor.setAccessible(true);
      Singleton reflectSingleton = constructor.newInstance();
      System.out.println(reflectSingleton == singleton);
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

執(zhí)行結(jié)果:

false

      運行結(jié)果說明,采用反射的方式另辟蹊徑實例了該類,導(dǎo)致程序中會存在不止一個實例。

    (2)解決方案

      其思想就是采用一個全局變量,來標(biāo)記是否已經(jīng)實例化過了,如果已經(jīng)實例化過了,第二次實例化的時候,拋出異常。實現(xiàn)代碼如下:

public class Singleton{
  private static volatile Singleton mInstance;
  private static volatile boolean mIsInstantiated = false;
  private Singleton(){
    if (mIsInstantiated){
      throw new RuntimeException("Has been instantiated, can not do it again!");
    }
    mIsInstantiated = true;
  }
  public static Singleton getInstance(){
    if(mInstance == null){
      synchronized (Singleton.class) {
        if(mInstance == null){
          mInstance = new Singleton();
        }
      }
    }
    return mInstance;
  }
}

執(zhí)行結(jié)果:

2、clone()對單例模式的破壞

       當(dāng)需要實現(xiàn)單例的類允許clone()時,如果處理不當(dāng),也會導(dǎo)致程序中出現(xiàn)不止一個實例。

    (1)案例

  一個實現(xiàn)了Cloneable接口單例類:

public class Singleton implements Cloneable{
  private static volatile Singleton mInstance;
  private Singleton(){
  }
  public static Singleton getInstance(){
    if(mInstance == null){
      synchronized (Singleton.class) {
        if(mInstance == null){
          mInstance = new Singleton();
        }
      }
    }
    return mInstance;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    // TODO Auto-generated method stub
    return super.clone();
  }
}

測試代碼:

public class SingletonDemo {

  public static void main(String[] args){
    try {
      Singleton singleton = Singleton.getInstance();
      Singleton cloneSingleton;
      cloneSingleton = (Singleton) Singleton.getInstance().clone();
      System.out.println(cloneSingleton == singleton);
    } catch (CloneNotSupportedException e) {
      e.printStackTrace();
    }
  }
}

執(zhí)行結(jié)果:

false

  (2)解決方案:

     解決思想是,重寫clone()方法,調(diào)clone()時直接返回已經(jīng)實例的對象

public class Singleton implements Cloneable{
  private static volatile Singleton mInstance;
  private Singleton(){
  }
  public static Singleton getInstance(){
    if(mInstance == null){
      synchronized (Singleton.class) {
        if(mInstance == null){
          mInstance = new Singleton();
        }
      }
    }
    return mInstance;
  }
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return mInstance;
  }
}

執(zhí)行結(jié)果:

true

3、序列化對單例模式的破壞

   在使用序列化/反序列化時,也會出現(xiàn)產(chǎn)生新實例對象的情況。

  (1)案例

      一個實現(xiàn)了序列化接口的單例類:

public class Singleton implements Serializable{
  private static volatile Singleton mInstance;
  private Singleton(){
  }
  public static Singleton getInstance(){
    if(mInstance == null){
      synchronized (Singleton.class) {
        if(mInstance == null){
          mInstance = new Singleton();
        }
      }
    }
    return mInstance;
  }
}

測試代碼:

public class SingletonDemo {

  public static void main(String[] args){
    try {
      Singleton singleton = Singleton.getInstance();
      FileOutputStream fos = new FileOutputStream("singleton.txt");
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(singleton);
      oos.close();
      fos.close();

      FileInputStream fis = new FileInputStream("singleton.txt");
      ObjectInputStream ois = new ObjectInputStream(fis);
      Singleton serializedSingleton = (Singleton) ois.readObject();
      fis.close();
      ois.close();
      System.out.println(serializedSingleton==singleton);
    } catch (Exception e) {
      e.printStackTrace();
    }

  }
}

     運行結(jié)果:

false

    (2)解決方案

    在反序列化時的回調(diào)方法 readResolve()中返回單例對象。

public class Singleton implements Serializable{
  private static volatile Singleton mInstance;
  private Singleton(){
  }
  public static Singleton getInstance(){
    if(mInstance == null){
      synchronized (Singleton.class) {
        if(mInstance == null){
          mInstance = new Singleton();
        }
      }
    }
    return mInstance;
  }

  protected Object readResolve() throws ObjectStreamException{
    return mInstance;
  }
}

結(jié)果:

true

       以上就是筆者目前已知的三種可以破壞單例模式的場景以及對應(yīng)的解決辦法,讀者如果知道還有其他的場景,記得一定要分享出來噢,正所謂“獨樂樂不如眾樂樂”!??!

       單例模式看起來是設(shè)計模式中最簡單的一個,但“麻雀雖小,五臟俱全”,其中有很多細(xì)節(jié)都是值得深究的。即便是本篇介紹的這幾個場景,也只是介紹了一些梗概而已,很多細(xì)節(jié)還需要讀者自己去試驗和推敲的,比如:通過枚舉方式實現(xiàn)單例模式,就不存在上述問題,而其它的實現(xiàn)方式似乎都存在上述問題!

       后記

       本篇參(剽)考(竊)了如下資料:http://m.fzitv.net/article/143047.htm

以上就是JAVA破壞單例模式的方式以及避免方法的詳細(xì)內(nèi)容,更多關(guān)于JAVA 單例模式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

玉树县| 水城县| 吉林市| 清河县| 大余县| 嘉定区| 潞城市| 商城县| 岳西县| 保定市| 普兰县| 广河县| 曲麻莱县| 吴忠市| 瓮安县| 娄底市| 建宁县| 中超| 九寨沟县| 宜都市| 大名县| 宜城市| 敦煌市| 平阳县| 石河子市| 宜州市| 时尚| 全椒县| 海南省| 垣曲县| 新巴尔虎左旗| 咸宁市| 綦江县| 保定市| 武义县| 莎车县| 武邑县| 浦东新区| 衡南县| 贵定县| 武胜县|