设计模式(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;//延迟加载
}
}