一、单例模式要点
1.单例,顾名思义,某个类仅仅能有一个实例。
2.它必须自行创建这个唯一的实例。
3.它必须自行向整个系统提供这个实例。
二、单例模式的三种实现
1.饿汉式单例类(类载入时就初始化)
代码实现
public class EagerSingleton { //私有的类成员常量 private static final EagerSingleton SINGLETON=new EagerSingleton(); //私有的默认构造方法。此类不能被继承 private EagerSingleton(){} //静态工厂方法 public static EagerSingleton getInstance(){ return SINGLETON; } }
Java语言中的单例类的一个最重要的特点是类的构造方法是私有的。从而避免外界利用构造方法直接创建出人意多飞实例。
2.懒汉式单例类(第一次调用才初始化。延迟)
代码实现
public class LazySingleton { private static LazySingleton singleton=null; //私有的默认构造方法,此类不能被继承 private LazySingleton(){} //同步。静态工厂方法,返回此类的唯一实例 public synchronized static LazySingleton getInstance(){ if(singleton==null){ singleton=new LazySingleton(); } return singleton; }
在懒汉式单例中,假设在多线程中訪问会出现线程安全问题,easy造成多个实例对象产生,因此对懒汉式单例须要进一步加强,代码例如以下:
public class DoubleCheckSingleton { private volatile static DoubleCheckSingleton singleton = null; // 私有的默认构造方法,此类不能被继承 private DoubleCheckSingleton() { } // 静态工厂方法,返回此类的唯一实例 public static DoubleCheckSingleton getInstance() { if (singleton == null) { synchronized (DoubleCheckSingleton.class) { if (singleton == null) { singleton = new DoubleCheckSingleton(); } } } return singleton; } }
3.登记式单例类
登记式单例类是为了克服饿汉式单例类和懒汉式单例类不可继承的缺点而设计的。
package com.zzs.singleton; import java.util.HashMap; public class RegSingleton { private static HashMap registry=new HashMap(); /**静态代码块 *静态代码块优先于主方法运行,而在类中定义的静态代码会优先于构造块运行,并且无论产生多少对象。静态代码块仅仅运行一次。 */ static{ RegSingleton singleton=new RegSingleton(); registry.put(singleton.getClass().getName(), singleton); } protected RegSingleton(){} public static RegSingleton getInstance(String name){ if(name==null){ name="com.zzs.singleton.RegSingleton"; } if(registry.get(name)==null){ try { registry.put(name, Class.forName(name).newInstance()); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return (RegSingleton) registry.get(name); } }
package com.zzs.singleton; public class RegSingletonChild extends RegSingleton { //因为子类必须同意父类以构造方法调用产生实例,所以它的构造方法必须是公开的。protected或public protected RegSingletonChild() { } //静态方法工厂 public static RegSingletonChild getInstance() { return (RegSingletonChild) RegSingleton .getInstance("com.zzs.singleton.RegSingletonChild"); } }
三、在什么情况下使用单例模式
使用单例模式的一个必要条件:在一个系统中要求仅仅有一个类的实例时应当使用单例模式。反过来说,假设一个类能够有几个实例共存,那么就没有必要使用单例类。java语言中的Runtime对象就是一个单例模式。
时间: 2024-10-23 01:19:41