[java设计模式]单例设计模式,程序也要进行计划生育。

引言

内存妈妈太累了,再也撑不起太多的对象了。
单例设计模式

单例设计模式

何为单例设计模式:
顾名思义,单:表示一个;:表示实例;单例:表示一个实例;也就是说我们的程序在运行的整个生命周期中,只创建一个对象,而不去创建多个对象。理解起来很简单吧。

何种场景只需要一个对象?
保证第一点,没有多个线程度这个对象的变量进行写操作,只要满足这一点,基本上都可以使用单例设计模式。比如:配置类,Spring中配置的Controller、Service、dao层的对象。

单例设计模式的特征:
不管你代码怎么写,只要满足以下特征即可:

  • 构造方法私有化。禁止外部创建对象。
  • 提供一个外部访问的接口。

常见的单例设计模式:

  1. 懒汉式
  2. 饿汉式
  3. 双重检测锁
  4. 静态内部类
  5. 枚举
    常见的这五种单例设计模式,也无非就是利用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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!