运维开发网

漫说单例模式--宝宝成长记 你真的了解了吗?

运维开发网 https://www.qedev.com 2020-11-30 08:32 出处:51CTO 作者:日常笔记
你就是单例你呱呱落地到这个世界的时候,这就是单例的产生,你是世界上唯一无二的存在。此时,你是父辈、祖辈的宝贝。他们都想和你亲近。publicclassSingleton{privatefinalstaticSingletonINSTANCE=newSingleton();//婴儿呱呱落地//PrivateconstructorsuppressesprivateSingleton(){}//defa
  1. 你就是单例

你呱呱落地到这个世界的时候,这就是单例的产生,你是世界上唯一无二的存在。

漫说单例模式--宝宝成长记 你真的了解了吗?

此时,你是父辈、祖辈的宝贝。他们都想和你亲近。

漫说单例模式--宝宝成长记 你真的了解了吗?

public class Singleton {
    private final static Singleton INSTANCE = new Singleton();  //婴儿呱呱落地

    // Private constructor suppresses   
    private Singleton() {}

    // default public constructor
    public static Singleton getInstance() {  //每个人都想抱你,和你亲近,你也想很多人亲近。
        return INSTANCE;
    }
  }

亲近就有两种:一种:别人想要抱你;另一种:你呼唤别人抱你。

第一种称之为:Eager initialization,如上面的代码所示。另一种称之为Lazy initialization。代码如下所示:

public class SingletonDemo {
    private static SingletonDemo instance = null;  //我很懒,你要想报我,你自己动手

    private SingletonDemo() {    }

    public static  SingletonDemo getInstance() {
        if (instance == null) {
                    instance = new SingletonDemo (); //你得到机会了。
        }
        return instance;
    }
}
  1. 竞争的产生

    很多人想报你和你亲近,可你只有一个呀,这就产生了矛盾,这就需要你来控制谁可以来抱你了。这就需要synchronization来控制。

public class SingletonDemo {
    private static SingletonDemo instance = null;

    private SingletonDemo() {    }

    public static synchronized SingletonDemo getInstance() {
        if (instance == null) {
                    instance = new SingletonDemo ();
        }
        return instance;
    }
}

为了让更多人可以抱你,你想出了更好的办法:

public class SingletonDemo {
    private static volatile SingletonDemo instance = null;

    private SingletonDemo() {    }

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

当然,因为怕出现问题,你想出了更巧的办法:双重检查锁

(Double-checked locking)

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

上述方法存在一定的风险,你可以在方法上再加入synchronized。

  1. 太复杂了,扛不住了,那就简单一点吧
public class Singleton {
   public final static Singleton INSTANCE = new Singleton();
   private Singleton() {
         // Exists only to defeat instantiation.
      }
}

然后你就可以直接使用了:

Singleton singleton = Singleton.INSTANCE;
      singleton.dothis();
      singleton.dothat();
      ...
  1. 上面产生单例的方法都是静态的,可以使用动态的方式吗?

    使用register机制来动态完成单例的实例化。动态化我们首先想到了什么?对了,是反射。

import java.util.HashMap;
import org.apache.log4j.Logger;
public class Singleton {
   private static HashMap map = new HashMap();
   private static Logger logger = Logger.getRootLogger();
   protected Singleton() {
      // Exists only to thwart instantiation
   }
   public static synchronized Singleton getInstance(String classname) {
      Singleton singleton = (Singleton)map.get(classname);
      if(singleton != null) {
         logger.info("got singleton from map: " + singleton);
         return singleton;
      }
      try {
         singleton = (Singleton)Class.forName(classname).newInstance();
      }
      catch(ClassNotFoundException cnf) {
         logger.fatal("Couldn't find class " + classname);    
      }
      catch(InstantiationException ie) {
         logger.fatal("Couldn't instantiate an object of type " + classname);    
      }
      catch(IllegalAccessException ia) {
         logger.fatal("Couldn't access class " + classname);    
      }
      map.put(classname, singleton);
      logger.info("created singleton: " + singleton);
      return singleton;
   }
}

为了更好的复用代码,我们该怎么做呢?封装!

import java.util.HashMap;
import org.apache.log4j.Logger;
public class SingletonRegistry {
   public static SingletonRegistry REGISTRY = new SingletonRegistry();
   private static HashMap map = new HashMap();
   private static Logger logger = Logger.getRootLogger();
   protected SingletonRegistry() {
      // Exists to defeat instantiation
   }
   public static synchronized Object getInstance(String classname) {
      Object singleton = map.get(classname);
      if(singleton != null) {
         return singleton;
      }
      try {
         singleton = Class.forName(classname).newInstance();
         logger.info("created singleton: " + singleton);
      }
      catch(ClassNotFoundException cnf) {
         logger.fatal("Couldn't find class " + classname);    
      }
      catch(InstantiationException ie) {
         logger.fatal("Couldn't instantiate an object of type " + 
                       classname);    
      }
      catch(IllegalAccessException ia) {
         logger.fatal("Couldn't access class " + classname);    
      }
      map.put(classname, singleton);
      return singleton;
   }
}

封装完成后,我们可以使用了。

import java.util.HashMap;
import org.apache.log4j.Logger;
public class Singleton {
   protected Singleton() {
      // Exists only to thwart instantiation.
   }
   public static Singleton getInstance() {
      return (Singleton)SingletonRegistry.REGISTRY.getInstance(classname);
   }
}
  1. 如果有很多小孩,医院是如何管理的呢?

漫说单例模式--宝宝成长记 你真的了解了吗?

可是有很多护士给宝贝护理,怎么保证我们家的宝宝得到照顾呢?保证一个护士负责一个婴儿就ok了

护士classloader 婴儿instance

private static Class getClass(String classname) 
                                         throws ClassNotFoundException {
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      if(classLoader == null)
         classLoader = Singleton.class.getClassLoader();
      return (classLoader.loadClass(classname));
   }
}
  1. 如何给婴儿包被褥呢?当脱掉一件后如果被包裹了两层就,不好了。为了避免这种情况,就需要检查包裹的效果了。
import org.apache.log4j.Logger;
public class Singleton implements java.io.Serializable {
   public static Singleton INSTANCE = new Singleton();
   protected Singleton() {
      // Exists only to thwart instantiation.
   }
      private Object readResolve() {  //保证包裹的检查返回同一种情况。
            return INSTANCE;
      }
}

参考:

  1. http://en.wikipedia.org/wiki/Singleton_pattern

  2. http://www.javaworld.com/article/2073352/core-java/simply-singleton.html

  3. 注意,以上图片均来自互联网,不一一标注了。

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号