单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类成为单例类,提供全局访问的方法。
实现单例模式的3个步骤:
1、private构造函数;
2、含有一个该类的private static对象;
3、提供public static方法,创建或获取本身的静态私有对象。
单例模式3种实现方式:饿汉式单例类、懒汉式单例类、Initialization on Demand Holder(IoDH)。
1、饿汉式单例类
1.1、关系图如下:
1.2、EagerSingleton
package com.java.designPattern.singleton;
/**
* 饿汉式单例类
*
*/
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
}
public EagerSingleton getInstance() {
return instance;
}
}
2、懒汉式单例类
2.1、关系图如下:
2.2、LazySingleton
package com.java.designPattern.singleton;
/**
* 单例模式 - 懒汉式
*
*/
public class LazySingleton {
/**
* 含有一个该类的静态私有对象
*/
private volatile static LazySingleton instance = null;
/**
* 私有的构造函数
*/
private LazySingleton() {
}
/**
* 静态共有函数,用于创建或获取本身的静态私有对象(双重校验锁)
*
* @return
*/
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
// 双重检查锁(Double-Check Locking)
if (instance == null) {
// 延迟加载(Lazy Load)技术
instance = new LazySingleton();
}
}
}
return instance;
}
}
3、Initialization on Demand Holder(IoDH) —— Java最优实现
代码如下:
1)Singleton
package com.java.designPattern.singleton;
/**
* 单例模式 - Initialization on Demand Holder(IoDH)
*
*/
public class Singleton {
/**
* 私有的构造函数
*/
private Singleton() {
}
/**
* 静态(static)内部类
*
*/
private static class HolderClass {
private final static Singleton instance = new Singleton();
}
/**
* 静态共有函数,用于创建或获取本身的静态私有对象(双重校验锁)
*
* @return
*/
public static Singleton getInstance() {
return HolderClass.instance;
}
}
2)Client
package com.java.designPattern.singleton;
/**
* 测试类
*
*/
public class Client {
public static void main(String[] args) {
Singleton singletonA = Singleton.getInstance();
Singleton singletonB = Singleton.getInstance();
System.out.println("singletonA == singletonB : " + (singletonA == singletonB));
System.out.println("singletonA.hashCode() : " + singletonA.hashCode());
System.out.println("singletonB.hashCode() " + singletonB.hashCode());
System.out.println("hashCode().singletonA == singletonB : " + (singletonA.hashCode() == singletonB.hashCode()));
}
}
输出:
singletonA == singletonB : true
singletonA.hashCode() : 2007692877
singletonB.hashCode() 2007692877
hashCode().singletonA == singletonB : true
总结:
1、优点:
(1)唯一实例,可以严格控制客户怎样以及何时访问;
(2)只有一个对象,节约系统资源,对于频繁创建和销毁的对象,可以提高系统的性能;
(3)基于单利模式,可以扩展为多例类,既节省系统资源,又解决了由于单利对象共享过多有损性能的问题。
2、缺点:
(1)没有抽象层,扩展又很大困难;
(2)单例类责任过重,在一定程度上违背了单一职责原则;
(3)自动垃圾回收技术,长时间不被利用的共享对象被自动销毁并回收资源,导致共享单例对象状态的丢失。
3、适用场景:
(1)只需要一个实例对象。例如:序列号生成器、资源管理器。资源消耗太大只允许创建一个对象。
(2)客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。