单利模式是确保系统中某一个类只要一个实例。单例的类图如下: 代码清单:单例通用模板,饿汉式,线程安全。
public class Singleton { /** * static 初始化一个实例 */ private static final Singleton singleton = new Singleton(); /** * 构造函数私有化,防止new */ private Singleton(){} /** * 通过该方法向外提供实例 */ public static Singleton getInstance(){ return singleton; } /** * 其他方法,尽量使用static */ public static void other(){ } }代码清单:双重检查判断单例,懒汉式,线程安全。
public class Singleton { /** * volatile修饰 */ private static volatile Singleton singleton; /** * 构造函数私有化,防止new */ private Singleton(){} /** * 通过该方法向外提供实例 */ public static Singleton getInstance(){ if(singleton == null){ synchronized(Singleton.class){ if(singleton == null){ singleton = new Singleton(); } } } return singleton; } /** * 其他方法,尽量使用static */ public static void other(){ } }代码清单:静态内部类,线程安全。
public class Singleton { /** * 静态内部类 */ private static class SingletonInstance{ private static final Singleton INSTANCE = new Singleton(); } /** * 构造函数私有化,防止new */ private Singleton(){} /** * 通过该方法向外提供实例 */ public static Singleton getInstance(){ return SingletonInstance.INSTANCE ; } /** * 其他方法,尽量使用static */ public static void other(){ } }代码清单:序列化与反序列化,静态内部类,线程安全。
public class Singleton implements Serializable{ private static final long serialVersionUID = 4615796391914001196L; /** * 静态内部类 */ private static class SingletonInstance{ private static final Singleton singleton = new Singleton(); } /** * 构造函数私有化,防止new */ private Singleton(){} /** * 序列化将这个类读入到内存(写入磁盘)中,而反序列化可以从内存(写入磁盘)中将其读出进而组装一个和 * 以前一摸一样的对象,不过当序列化遇到单例的时候,就出现了问题,这样破坏了单例的规则。JVM从内存中 * 反序列化一个新对象时,就会自动调用这个readResolve()来返回指定好的对象了,单例规则也就得到了保证。 */ protected Object readResolve() throws ObjectStreamException{ return SingletonInstance.singleton ; } /** * 通过该方法向外提供实例 */ public static Singleton getInstance(){ return SingletonInstance.singleton ; } /** * 其他方法,尽量使用static */ public static void other(){ System.out.println(getInstance().hashCode()); } }代码清单:静态代码块,饿汉式,线程安全。
public class Singleton { private static Singleton singleton = null; /** * 构造函数私有化,防止new */ private Singleton(){} /** * 构造函数私有化,防止new */ static { singleton = new Singleton(); } /** * 通过该方法向外提供实例 */ public static Singleton getInstance(){ return singleton; } /** * 其他方法,尽量使用static */ public static void other(){ } }代码清单:枚举数据类型实现单例模式,饿汉式,线程安全。
public class SingletonEnum { public enum Singleton { factory; private String str; /** * 构造方法会被自动调用 */ private Singleton() { Random ran = new Random(1000); this.str = ran.toString(); } public String str() { return str; } } /** * 获取实例 */ public String getInstance() { return Singleton.factory.str(); } }单例模式的缺点:
单例模式一般没有接口,扩展困难,若要修改,除了修改代码基本上没有其他方法可以实现;单例模式不利于测试;单利模式与单一职责有冲突;注意:方法里面的变量是线程安全的。
