设计模式从入门到方式(一)单例模式
单例模式
单例模式便是创建型设计模式的一种,单例模式确保某一个类在系统中只有一个实例。
本次使用实现单例模式只列出了线程安全的几种形式
实现步骤
- 构造器私有化,防止外部new对象造成多实例.
- 内部提供一个static 对象用于保存全局唯一单例的实体
- 定义一个静态方法返回该对象
饿汉式
在加载类的时候直接将对象实例,无视是否使用。
-
优点
简单 线程安全
-
缺点
当类被加载的时候即创建单例对象,如果没有使用该对象会造成内存浪费
public class EagerSingleTon {
private EagerSingleTon() {
}
private static EagerSingleTon INSTANCE = new EagerSingleTon();
public static EagerSingleTon getInstance() {
return INSTANCE;
}
}
懒汉式
双重检查
-
优点
线程安全 懒加载 如果没有用到这个单例则不会创建,节省内存
-
缺点
实现相对繁琐
public class DoubleCheckSingleTon {
private DoubleCheckSingleTon() {
}
private static volatile DoubleCheckSingleTon INSTANCE = null;
public static DoubleCheckSingleTon getINSTANCE() {
// 多线程首次进入判断INSTANCE 是否为空 如果不为空直接返回
if (INSTANCE == null) {
// 多线程同时进入 加锁实例化 其他线程再次进入之后INSTANCE不为空,不会进入第二次if判断
synchronized (DoubleCheckSingleTon.class) {
if (INSTANCE == null) {
INSTANCE = new DoubleCheckSingleTon();
}
}
}
return INSTANCE;
}
}
静态内部类 InstanceHolder
利用Java的类加载机制,外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。即当SingleTon第一次被加载时,并不需要去加载SingleTonHolder,但调用getInstance方法才会去实例化对象。
调用getInstance方法会导致Java虚拟机加载InstanceHolder这个静态内部类,在静态内部中实例化外部的对象。
线程安全,实现简单 推荐一种实现方式
public class StaticInnerClassInstanceHolder {
private StaticInnerClassInstanceHolder() {
}
private static class InstanceHolder {
private static StaticInnerClassInstanceHolder INSTANCE = new StaticInnerClassInstanceHolder();
}
public static StaticInnerClassInstanceHolder getInstance() {
return InstanceHolder.INSTANCE;
}
}
枚举
枚举单例 枚举在java中与普通类一样,都能拥有字段与方法,而且枚举实例创建是线程安全的,在任何情况下,它都是一个单例。
实现简单 线程安全 推荐使用
public enum EnumSingleTone {
INSTANCE;
private String sayHello(String name){
return "hello" +name;
}
public static void main(String[] args) {
System.out.println(EnumSingleTone.INSTANCE.sayHello("world"));
}
}
或者这样实现
public class EnumSingleToneDemo {
private EnumSingleToneDemo() {
// empty
}
private enum Singleton {
INSTANCE;
private final EnumSingleToneDemo instance;
Singleton() {
// 枚举初始化加载只会执行一次
this.instance = new EnumSingleToneDemo();
}
public EnumSingleToneDemo getInstance() {
return instance;
}
}
public static EnumSingleToneDemo getInstance() {
return Singleton.INSTANCE.getInstance();
}
}