设计模式之单列模式
单列模式:
概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
1、单列类只能有一个实列
2、单列类必须自己创建自己的实列
3、单列类必须提供给所有其他对象获得该实列的方法
单列模式——饿汉式:
优点:线程安全、执行效率高
缺点:类加载时就初始化,浪费内存,容易产生垃圾对象(类加载时创建了对象,又没有调用方法获取实列)
/**
* 单列模式——饿汉式
* @author ypf
*
*/
public class Singleton1 {
private static Singleton1 instance = new Singleton1();
//构造方法私有化
private Singleton1() {
}
public static Singleton1 getInstance() {return instance;
}
}
单列模式——懒汉式:
优点:第一次使用时才初始化,避免了内存浪费;
缺点:线程不安全,不支持多线程;
/**
* 单列模式——懒汉式
* @author ypf
*
*/
public class Singleton2 {
private static Singleton2 instance;
//构造方法私有化
private Singleton2() {
}
public static Singleton2 getInstance() {
if(instance == null) {
instance = new Singleton2();
}
return instance;
}
}
单列模式——懒汉式(简单优化):
优点:实现了lazy-load(懒加载),第一次使用时才初始化,避免了内存浪费,线程安全;
缺点:执行效率低
/** * 单列模式——懒汉式(简单优化) * @author ypf * */ public class Singleton3 { private static Singleton3 instance; //构造方法私有化 private Singleton3() { }
//对方法加synchronized关键字 public synchronized static Singleton3 getInstance() { if(instance == null) { instance = new Singleton3();
}
return instance; } }
单列模式——双重检测锁式:
优点:第一次使用时才初始化,避免了内存浪费,线程安全,在多线程情况下也能保持高性能;
缺点 : 实现较复杂
在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后再取变量值时,就直接从寄存器中取值;
/**
* 单列模式——双重检测锁式
* @author ypf
*
*/
public class Singleton4 {
//给变量加volatile关键字,为了让编译器在使用这个变量时必须每次都重新读取这个变量的值,而不是使用保存在寄存器里的备份
private static volatile Singleton4 instance;
//构造方法私有化
private Singleton4() {
}
public synchronized static Singleton4 getInstance() {
//避免每次都获取锁
if(instance == null) {
synchronized (Singleton4.class) {
if(instance == null) {
instance = new Singleton4();
}
}
}
return instance;
}
}
单列模式——静态内部类式:
优点:线程安全、延迟加载、可以达到与双重检测锁一样的效果,但实现更简单,这种方式只适用于静态域的情况。
/**
* 单列模式——静态内部类
* @author ypf
*
*/
public class Singleton5 {
private static class getSingleton{
private static final Singleton5 INSTANCE = new Singleton5();
}
//构造方法私有化
private Singleton5() {
}
public static Singleton5 getInstance() {
return getSingleton.INSTANCE;
}
}
单列模式——枚举式:
优点:避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
刚开始看到枚举式是这样的,
/**
* 单列模式——枚举
* @author ypf
*
*/
public enum Singleton6 {
INSTANCE;
public void anyMethod(){
}
}
测试一下:
/**
* 单列模式——枚举
* @author ypf
*
*/
public enum Singleton6 {
INSTANCE;
private Singleton6() {
System.out.println("构造方法");
}
public void anyMethod(){
System.out.println(123);
}
}
测试代码:
public class TestSingleton {
public static void main(String[] args) {
Singleton6 instance = Singleton6.INSTANCE;
Singleton6 instance1 = Singleton6.INSTANCE;
Singleton6 instance2 = Singleton6.INSTANCE;
Singleton6 instance3 = Singleton6.INSTANCE;
System.out.println(instance.hashCode());
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
instance.anyMethod();
instance1.anyMethod();
instance2.anyMethod();
instance3.anyMethod();
}
}
效果展示:
可以看到构造方法只执行了一次,即是同一个实列