设计模式之单例模式

Posted 李三岁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之单例模式相关的知识,希望对你有一定的参考价值。

设计模式(Design pattern)提供了在软件开发过程中面临的一系列问题的最佳解决方案,是Java开发者必修的一门课程。主要分创建型模式、结构型模式和行为型模式。单例模式是Java中最简单的设计模式之一,属于创建型模式。

单例模式

单例模式从字面的角度来讲 单一实例 / 一个对象 的 模式.
那么首先我们需要考虑的是谁去创建这个对象,或者说拿什么去创建这个对象.
创建对象的时候我们都需要调用我们类中的构造方法,那么谁都可以调用我们的构造方法,我们就没办法使其有且只有一个对象,那么如何才能让一个类有且只有一个对象呢。
我们需要将构造方法私有化,并且在类中自己去创建这个唯一的实例,然后提供一个可以被外部访问的方法。

单例模式中最常用的两种:饿汉式,懒汉式

一、饿汉式

顾名思义:饿,饥不择食,只要有,我就吃.
就是指当类被加载的时候就会创建对象.

/**
 * Author:Lss
 * Date: 2020-09-27 11:16
 * Description: 饿汉式单例模式
 * 优点:类加载时完成初始化,并且没有枷锁,提高执行效率.
 * 缺点:类加载的时候就初始化,不管用与不用都占用内存空间,浪费了内存,且加载速度慢.
 */
public class HungryPattern {
     //通过private封装创建好的对象 -- 私有属性对外界不可见
     private static final HungryPattern hungryPattern = new HungryPattern();
     //创建对象的时候都会调用我们的构造方法
     //私有化构造方法 -- 目的就是为了控制外界创建对象的权限
     private HungryPattern() {
        System.out.println("HungryPattern对象被创建了!");
     }
   /**
    * 既然私有的构造方式,没有办法new对象了,也就没办法通过 引用.方法 的方式来调用,
    * 那么还想调用就必须将其声明为static静态的,这样就可以通过类名.调用,
    * 而且什么地方都可以访问就必须将访问控制修饰符设置为 public
    */
     public static HungryPattern getInstance(){
            return hungryPattern;
     }
}

二、懒汉式

顾名思义:懒,不会提前做准备工作,只有逼到份儿上,才会做.
就是指当第一次被使用的时候才会创建对象.

1.懒汉式单例模式(线程不安全)
/**
 * Author:Lss
 * Date: 2020-09-27 11:18
 * Description: 懒汉式单例模式(线程不安全)
 * 优点:第一次调用才创建对象,避免内存浪费。
 * 缺点:多线程不安全,因为没有加锁 synchronized,不能保证单例
 * 不推荐使用
 */
public class LazyPattern {
    //封装创建好的对象 -- 先不创建对象,啥时候用啥时候创建(懒)
    private static LazyPattern lazyPattern = null;
    //私有化构造方法  --  目的就是为了控制外界创建对象的权限
    private LazyPattern(){
        System.out.println("LazyPattern对象被创建了!");
    }
    //提供了公开的获取对象的方法
    public static LazyPattern getInstance(){
        if (lazyPattern == null){
            lazyPattern = new LazyPattern();
        }
        return lazyPattern;//延迟加载
    }
}
2.懒汉式单例模式(线程安全)
/**
 * Author:Lss
 * Date: 2020-09-27 11:23
 * Description: 懒汉式单例模式(线程安全 - 锁方法)
 * 优点:第一次调用才创建对象,避免内存浪费。
 * 缺点:加锁synchronized保证了单例,但是锁的范围太大,影响效率
 * 不推荐使用
 */
public class LazyPattern {
    //封装创建好的对象 -- 先不创建对象,啥时候用啥时候创建(懒)
    private static LazyPattern lazyPattern = null;
    //私有化构造方法  --  目的就是为了控制外界创建对象的权限
    private LazyPattern(){
        System.out.println("LazyPattern对象被创建了!");
    }
    //提供了公开的获取对象的方法
    public static synchronized LazyPattern getInstance(){
        if (lazyPattern == null){
            lazyPattern = new LazyPattern();
        }
        return lazyPattern;//延迟加载
    }
}
3.懒汉式单例模式(线程安全 -- 双重校验)

双重校验:我们又称双检锁/双重校验锁(DCL,即 double-checked locking)

/**
 * Author:Lss
 * Date: 2020-09-27 11:28
 * Description: 懒汉式单例模式(线程安全 - 双重检查)
 * 优点:双重检查在多线程安全的情况下,减小了锁的范围,即保证了安全的情况下也保持了高性能
 * 推荐使用
 */
public class LazyPattern {
    //封装创建好的对象 -- 先不创建对象,啥时候用啥时候创建(懒)
    private static LazyPattern lazyPattern = null;
    //私有化构造方法  --  目的就是为了控制外界创建对象的权限
    private LazyPattern(){
        System.out.println("LazyPattern对象被创建了!");
    }
    //提供了公开的获取对象的方法
    public static LazyPattern getInstance(){
        //先检查实例是否存在,如果不存在才进入下面的同步块
        if (lazyPattern == null){
            //同步块
            synchronized(LazyPattern.class){
                //再次检查实例是否存在,如果不存在才创建实例
                if (lazyPattern == null){
                    lazyPattern = new LazyPattern();
                }
            }
        }
        return lazyPattern;//延迟加载
    }
}
4.懒汉式单例模式(线程安全 -- 静态内部类实现)
/**
 * Author:Lss
 * Date: 2020-09-27 11:39
 * Description: 懒汉式单例模式(线程安全 - 静态内部类实现)
 
 * 推荐使用
 */
public class LazyPattern {
    //私有化构造方法  --  目的就是为了控制外界创建对象的权限
    private LazyPattern(){
        System.out.println("LazyPattern对象被创建了!");
    }
    private static class InnnerSingleton{
        private static final LazyPattern LAZY_PATTERN = new lazyPattern();
    }
    //提供了公开的获取对象的方法
    public static LazyPattern getInstance(){    
        return InnnerSingleton.LAZY_PATTERN;//延迟加载
    }
}

以上是关于设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之单例模式

Java设计模式之单例模式

设计模式之单例模式以及简单代码实现

设计模式之单例设计模式

设计模式之单例模式

设计模式之单例模式