博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
漫说单例模式--宝宝成长记 你真的了解了吗?
阅读量:7049 次
发布时间:2019-06-28

本文共 5726 字,大约阅读时间需要 19 分钟。

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;    }}

 

2. 竞争的产生

    很多人想报你和你亲近,可你只有一个呀,这就产生了矛盾,这就需要你来控制谁可以来抱你了。这就需要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。

3. 太复杂了,扛不住了,那就简单一点吧

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();      ...

4. 上面产生单例的方法都是静态的,可以使用动态的方式吗?

    使用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);   }}

5. 如果有很多小孩,医院是如何管理的呢?

可是有很多护士给宝贝护理,怎么保证我们家的宝宝得到照顾呢?保证一个护士负责一个婴儿就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));   }}

6. 如何给婴儿包被褥呢?当脱掉一件后如果被包裹了两层就,不好了。为了避免这种情况,就需要检查包裹的效果了。

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. 注意,以上图片均来自互联网,不一一标注了。

 

 

转载地址:http://dodol.baihongyu.com/

你可能感兴趣的文章
Spring Boot [组件学习-Spring Data JPA]
查看>>
百度云磁盘CDS、对象存储BOS技术深度解析
查看>>
Deno:来自Node之父的V8 TypeScript运行时
查看>>
姜宁谈红帽绩效考核:不关心员工具体做什么
查看>>
Trello中的Scrum
查看>>
Pivotal发布了具有新应用程序托管工具的Spring Cloud Data 1.6
查看>>
Scala类型系统的目的——Martin Odersky访谈(三)
查看>>
无服务器计算的黑暗面:程序移植没那么容易
查看>>
Ockam为物联网设备带来区块链无服务器身份识别
查看>>
Agile Consortium的营销交流章
查看>>
Java二十年历程回顾
查看>>
干研发更喜欢无服务器,搞DevOps偏爱容器?
查看>>
《领导力敏捷》作者访谈
查看>>
Vue2.0 学习笔记
查看>>
研究人员发现:基于文本的AI模型容易受到改述攻击
查看>>
物联网技术周报第 103 期: DIY 智能音箱:基于 Raspberry Pi + Snowboy + AVS
查看>>
Creating Great Teams作者问答
查看>>
Azure编配器简化有状态无服务器工作流的创建
查看>>
AWS App Mesh:用于Envoy的服务网格控制平面
查看>>
专访ThoughtWorks王磊:从单块架构到微服务架构
查看>>