单例模式可以说是简单又复杂的一种设计模式!
单例就是对象只创建一个实例,并且提供一个全局的访问。但是说单例模式是复杂的设计模式也一点没错,因为涉及到DCL双锁检测(double checked locking)的讨论、涉及到多个
类加载器(ClassLoader)协同时、涉及到跨JVM(集群、远程EJB等)时、涉及到单例对象被销毁后重建等!那么这也就不是一个简单的设计模式了!首先,我创建一个简单的单例类吧!
package com.taobao.design; import java.io.Serializable; /** * 单例模式:创建型 */ public class SingletonA { private static SingletonA instance = null; public static SingletonA getInstance() { if(instance==null){ //line1 instance = new SingletonA(); //line2 } return instance; } } /** * 当多线程时,如果一个线程执行到line1时,另一个线程刚刚执行完line2,那么线程1就会再去new一个对象, * 所以上面这种情况就有可能new出两个对象那么哪个才是我们需要的对象呢?为了防止这种情况发生,那么我 * 把getInstance方法改成同步的! */ class SingletonB { private static SingletonB instance = null; public synchronized static SingletonB getInstance() { if(instance==null){ instance = new SingletonB(); } return instance; } } /** * 好!这下问题又来了!同步问题是解决了!什么问题呢!每次去调用getInstance方法时,都会有很大的性能 * 问题,比如当两个线程现时执行到getInstance方法时,那其中某个线程肯定要等另一个线程执行完才能执行 * ,所以至 少在至少耗时比例上存在很大性能问题的!接下来,把同步方法情改成同步代码块,在同步之前, * 做一下判断,双重锁定检查(DCL),这样应该解决了耗时问题了!但是总的说来一个单例这样是不上太复杂了 */ class SingletonC{ private static SingletonC instance = null; public static SingletonC getInstance() { if(instance==null){ synchronized(SingletonC.class){ if(instance==null){ instance = new SingletonC(); } } } return instance; } } /** * 返璞归真,一个类在一个ClassLoader中只会被初始化一次,那我在初始化时就把对象new出来不就可以了吗? * 哈哈 !原来这么简单! */ class SingletonD{ private static SingletonD instance = new SingletonD(); public static SingletonD getInstance(){ return instance; } } /** * 但是这样还存在一个问题,什么问题呢?上面这总是属于‘饿汉式’的创建方式,如果说要在创建之前做一些操作 * ,比如读取配置文件,或者创建的时候必须传递某个参数给它,那该怎么办啊?ok,那我写个内部类用来创建对 * 象,这样应该可以了吧!但是创建对象主要是通过1、new对象 2、反射构造单例对象 3、序列化构造单例,为了 * 防止这样创建对象,那我还要加两个方法SingletonE()和readResolve(),ok,现在应该基本满足需求了吧! */ class SingletonE implements Serializable{ private static class Singleton{ static final SingletonE instance = new SingletonE(); } private static SingletonE getInstance(){ return Singleton.instance; } //防止new private SingletonE(){} //防止通过反序列化得到对象 private Object readResolve() { return getInstance(); } }
总结:具体该如果创建单例,当然还是看情况而定,没有哪种创建方法是万能的!