单例模式(Singleton Pattern)
单例模式确保一个类仅有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。
单例模式只包含一个单例角色:单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它,在单例类的内部实现只生成一个实例,同时它提供一个静态的工厂方法,让客户可以使用它的唯一实例,该模式中包含一个静态私有成员变量与静态公有的工厂方法,该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。
单例模式的主要优点在于提供了对唯一实例的受控访问并可以节约系统资源;其主要缺点在于因为缺少抽象层而难以扩展,且单例类职责过重。单例模式适用情况包括:系统只需要一个实例对象;客户调用类的单个实例只允许使用一个公共访问点。
参与者与协作
参与者包括:
单件(Singleton):提供访问单件的接口;负责实现单件。
客户(Client):使用单件。
参与者的协作包括:
客户通过单件提供的 getInstance() 接口访问唯一的单件对象。
1.饿汉式单例-线程安全(立即加载方式)
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
2.懒汉式单例-线程不安全(延迟加载方式)
public class Singleton {
private static Singleton instance= null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.懒汉式单例-线程安全(延迟加载方式)
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4.双重校验锁-线程安全
public class Singleton {
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
5.静态内部类实现
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getinstance() {
return SingletonHolder.INSTANCE;
}
}
6.枚举实现
public class SingletonFactory {
private enum EnmuSingleton {
Singleton;
private Singleton singleton;
private EnmuSingleton() {
singleton = new Singleton();
}
public Singleton getInstance() {
return singleton;
}
}
public static Singleton getInstance() {
return EnmuSingleton.Singleton.getInstance();
}
}
class Singleton {
public Singleton() {
}
}
饿汉式单例与懒汉式单例类比较
饿汉式单例类在自己被加载时就将自己实例化。单从资源利用效率角度来讲,这个比懒汉式单例类稍差些。从速度和反应时间角度来讲,则比懒汉式单例类稍好些。
懒汉式单例类在实例化时,必须处理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过同步化机制进行控制。
Head First设计模式(中文版) Eric Freeman,ElElisabeth Freeman 编著
ISBN:978-7-5083-5393-7