[java设计模式]单例设计模式,程序也要进行计划生育。
引言
内存妈妈太累了,再也撑不起太多的对象了。
单例设计模式
何为单例设计模式:
顾名思义,单:表示一个;例:表示实例;单例:表示一个实例;也就是说我们的程序在运行的整个生命周期中,只创建一个对象,而不去创建多个对象。理解起来很简单吧。
何种场景只需要一个对象?
保证第一点,没有多个线程度这个对象的变量进行写操作,只要满足这一点,基本上都可以使用单例设计模式。比如:配置类,Spring中配置的Controller、Service、dao层的对象。
单例设计模式的特征:
不管你代码怎么写,只要满足以下特征即可:
- 构造方法私有化。禁止外部创建对象。
- 提供一个外部访问的接口。
常见的单例设计模式:
- 懒汉式
- 饿汉式
- 双重检测锁
- 静态内部类
- 枚举
常见的这五种单例设计模式,也无非就是利用JVM的特性,对何时进行加载,做了简单的区分。是程序启动的时候加载?还是类初始化的时候加载?
代码具体实现如下:
懒汉式
简单理解就是不让jvm启动的时候对单例进行加载,好处就是节约内存。可不嘛,不加载那么多对象,当然节省内存了。
/**
* @ClassName : lazybones 懒汉单例
* @Description : 懒汉设计模式,加载的时候不进行初始化。
*/
public class Lazybones {
private static Lazybones instance;
/** * 私有构造方法,防止外部创建对象 */
private Lazybones() {
}
/** * 外部过去实例的通道。
*
* @return
*/
public static synchronized Lazybones getInstance() {
if (instance == null) {
instance = new Lazybones();
} return instance;
}
}
饿汉式
简单理解就是JVM启动的时候就进行加载这个单例对象。好处就是再使用的时候,直接获取对象进行调用即可。因为类只会加载一次,所以对象也只会被创建一次。
/**
* @ClassName : Eager //饿汉单例
* @Description : //类加载的时候,进行初始化。
*/
public class Hungry {
private static Hungry instance = new Hungry();
/**
* 私有构造方法
*/
private Hungry() {
}
/**
* 外部过去实例的通道
* @return
*/
public static Hungry getInstance() {
return instance;
}
}
双重检测锁
其实就是针对懒汉模式的一种优化,我们直接在方法上加锁,导致每次获取这个对象的时候,都需要先获取锁,效率太低了。 但是双重检测锁有一个坑,后续慢慢的讲。
/**
* @ClassName : DoubleDetectionLock //双重检测锁
* @Description : 双重检测锁,优化了懒汉单例模式的性能问题,通过加volatile关键是防止出现指令重排序。
*/
public class DoubleDetectionLock {
// volatile关键字可以防止指令重排序,避免产生bug
private static volatile DoubleDetectionLock instance;
/**
* 私有构造方法
*/
private DoubleDetectionLock() {
}
/**
* 外部获取渠道。
* @return
*/
public static DoubleDetectionLock getInstance() {
if (instance == null) {
synchronized (DoubleDetectionLock.class) {
if (instance == null){
instance = new DoubleDetectionLock();
}
}
}
return instance;
}
}
静态内部类
此方式也满足懒加载,因为即使内部类只有在自己被调用的时候才会进行初始化。而且兼顾使用到了类只被加载一次的特性。
/**
* @ClassName : InnerClass 内部静态类单例
* @Description : 内部静态类只有被去调用的时候,才进行初始化。
*/
public class InnerClass {
/**
* 私有构造方法
*/
private InnerClass(){
}
/**
* 内部类初始化的时候,创建。
*/
private static class Instance{
private static InnerClass instance = new InnerClass();
}
/**
* 外部获取的通道
* @return
*/
public static final InnerClass getInstance(){
return Instance.instance;
}
}
枚举类
天然的单例设计模式,这个平常用的不太多
/**
* 枚举也是天然的单例模式
*/
public enum EnumSingleton {
INSTANCE;
}
结尾
单例设计模式差不多,到此为止了。下一篇讲讲怎么去破解单例设计模式,以及怎么去防护。
本作品采用《CC 协议》,转载必须注明作者和本文链接