- 只能产生一个实例对象。实例为静态成员,构造方法为private,静态方法返回惟一实例。
- 单例类一般不要实现Cloneable接口,若一个类实现了Cloneable接口且实现了clone()方法,那么这个类可以被复制,类复制时不需要调用构造方法。单例将被破坏。
- 一个单例对象在内存中长久不使用,JVM会认为这个对象是一个垃圾,将会对其进行回收。但若采用J2EE容器或框架级容器(如Spring容器),可以让对象长久驻留内存。
- spring中每个bean默认均为单例,这样做spring容器可以管理bean的生命周期。若采用非单例模式(如prototype),则bean初始化后的管理交由j2ee容器管理,spring容器不再管理。
代码示例
饱汉式:线程不安全,可通过synchronized来解决
public class Singleton { private static Singleton item; private Singleton(){} public static Singleton getInstance() { if(item==null) item = new Singleton(); return item; } }
线程安全:
public class Singleton { private static Singleton item; private Singleton(){} public static Singleton getInstance() { if(item==null){ synchronized (Singleton.class) { if (item == null) {// Double checked item = new Singleton(); } } } return item; } }
饿汉式
public class Singleton { private static Singleton item = new Singleton(); private Singleton(){} public static Singleton getInstance() { return item; } }
多例模式
- 定义:三个static变量:最大实例数量maxInstanceNum,当前实例编号nowInstanceNum,实例列表instanceList。构造方法为private
- 一个static代码块:此代码块中生成所有实例,并将其添加到实例列表instanceList中。
- 一个static方法getInstance:获取0-maxInstanceNum间的一个随机整数random.nextInt(maxInstanceNum),从实例列表instanceList中获取索引为此值的实例。
- 考虑到多线程环境,可以用Vector代替ArrayList
代码:
public class Multiton { private static int maxInstanceNum=10;//最大实例数量 private static int nowInstanceNum=0;//当前实便编号 private static List<Multiton> instanceList = new ArrayList<Multiton>(); private static List<String> instanceNameList = new ArrayList<String>(); static{//把所有的皇帝都产生出来 for(int i=0;i<maxInstanceNum;i++){ instanceList.add(new Multiton("皇"+(i+1)+"帝")); } } private Multiton(String name) { instanceNameList.add(name); } public static Multiton getInstance(){ Random random = new Random(); nowInstanceNum = random.nextInt(maxInstanceNum);//随机拉出一个皇帝 return (Multiton)instanceList.get(nowInstanceNum); } public static void emperorInfo(){ System.out.println(instanceNameList.get(nowInstanceNum)); } } public class Client { public static void main(String[] args) { for(int i=0;i<100;i++){ Multiton.getInstance(); System.out.print("第"+(i+1)+"个大臣参拜的是:"); Multiton.emperorInfo(); } } }