Java 单例模式

简介: Java 单例模式


什么是单例模式?

保证整个系统中一个类只有一个对象的实例,实现这种功能的方式就叫单例模式

饿汉式

特点:无论需不需要,都会加载对象

package com.wyh.single;
/**
 * @program: JUC
 * @description: 单例模式--饿汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:17
 **/
//饿汉式单例  一上来就能把东西接受加载 有可能会浪费内存
//单例模式最重要的思想:构造器私有 一旦构造器私有了,那么别人就无法new这个对象了 就保证内存种只有一个对象
public class Hungry {
//一上来就接受  可能浪费空间
    //正确的思想是:应该判断是否需要使用资源,需要使用的话才进行接受加载避免资源浪费,也就是懒汉模式
    private byte[] data1=new byte[1024*1024];
private byte[] data2=new byte[1024*1024];
private byte[] data3=new byte[1024*1024];
private byte[] data4=new byte[1024*1024];
//构造器私有 保证别人无法new这个对象,间接保证内存种只有一个实例
    private Hungry(){
    }
//饿汉式单例不管怎么样,一上来先加载对象 也是唯一的对象
    private final  static Hungry hungry=new Hungry();
//对外方法 获取对象实例
    public static Hungry getInstance(){
return hungry;
    }
}

DCL懒汉式

特点:会通过双重锁判断对象是否需要加载

package com.wyh.single;
/**
 * @program: JUC
 * @description: 单例模式--懒汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:29
 **/
//懒汉模式相对于饿汉模式更加安全,会先判断是否需要使用资源,需要使用的话才进行加载,避免了资源浪费
public class Lazy {
//构造器私有
    private Lazy() {
        System.out.println(Thread.currentThread().getName() + "ok");
    }
//加载对象 不会直接一上来就加载对象 而是会进行判断是否需要进行使用
    private  static Lazy lazy;
//获取实例方法
    public static Lazy getInstance(){
//双重检测锁模式的懒汉式单例 DCL懒汉式单例
        //判断对象不为空 不为空才会创建
        if(lazy==null){
//保证Lazy只有一个 锁的是class
            synchronized (Lazy.class){
if(lazy==null){
lazy=new Lazy();
                }
            }
        }
return lazy;
    }
//问题: 单线程下这个懒汉单例确实OK的,但是多线程并发就不行了
    //以下为代码测试 多线程并发操作
    public static void main(String[] args){
//10条线程并发测试
        for (int i = 1; i <= 10; i++) {
new Thread(()->{
                Lazy.getInstance();
            }).start();
        }
//如何解决这个问题呢?
        //获取对象实例的时候加synchronized锁
    }
}

那么,以上代码没有问题吗?

有的,因为创建实例对象并不是一个安全操作,在底层它分为三个步骤

1 分配内存空间
2 执行构造方法,初始化对象
3 把这个对象分配个这个内存空间,但是可能会被指令重排,所以必须使用volatile修饰懒汉实例对象,防止指令重排
//为了防止指令重排 懒汉对象必须使用volatile进行修饰防止指令重排!
private  static volatile Lazy lazy;

懒汉单例安全完整代码如下

package com.wyh.single;
/**
 * @program: JUC
 * @description: 单例模式--懒汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:29
 **/
//懒汉模式相对于饿汉模式更加安全,会先判断是否需要使用资源,需要使用的话才进行加载,避免了资源浪费
public class Lazy {
//构造器私有
    private Lazy() {
    }
//加载对象 不会直接一上来就加载对象 而是会进行判断是否需要进行使用
    //为了防止指令重排 懒汉对象必须使用volatile进行修饰防止指令重排!
    private  static volatile Lazy lazy;
//获取实例方法
    public static Lazy getInstance(){
//双重检测锁模式的懒汉式单例 DCL懒汉式单例
        //判断对象不为空 不为空才会创建
        if(lazy==null){
//保证Lazy只有一个 锁的是class
            synchronized (Lazy.class){
if(lazy==null){
lazy=new Lazy(); //创建对象不是一个原子性操作
                    //创建分为三步 有可能会被指令重排 需要volatile修饰对象
                    //1 分配内存空间 2执行构造方法,初始化对象 3把这个对象指向这个空间
                }
            }
        }
return lazy;
    }
}

静态内部类创建单例对象(不建议使用)

package com.wyh.single;
/**
 * @program: JUC
 * @description: 单例模式--静态内部类
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:53
 **/
//使用静态内部类实现单例模式
//把单例模式放在内部类种创建,创建的时候调用内部类创建对象
public class Holder {
//只要是单例模型 必须构造器私有
    private Holder() {
    }
public static Holder getInstance(){
//调用内部类获取单例对象
            return InnerClass.holder;
    }
//内部类
    public static class InnerClass{
//单例对象
        private static final Holder holder=new Holder();
    }
}

通过反射破坏懒汉单例模式

1 1个反射对象

package com.wyh.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
 * @program: JUC
 * @description: 单例模式--懒汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:29
 **/
//懒汉模式相对于饿汉模式更加安全,会先判断是否需要使用资源,需要使用的话才进行加载,避免了资源浪费
public class Lazy {
//构造器私有
    private Lazy() {
        System.out.println(Thread.currentThread().getName() + "ok");
    }
//加载对象 不会直接一上来就加载对象 而是会进行判断是否需要进行使用
    //为了防止指令重排 懒汉对象必须使用volatile进行修饰防止指令重排!
    private  static volatile Lazy lazy;
//获取实例方法
    public static Lazy getInstance(){
//双重检测锁模式的懒汉式单例 DCL懒汉式单例
        //判断对象不为空 不为空才会创建
        if(lazy==null){
//保证Lazy只有一个 锁的是class
            synchronized (Lazy.class){
if(lazy==null){
lazy=new Lazy(); //创建对象不是一个原子性操作
                    //创建分为三步
                    //1 分配内存空间
                    //2执行构造方法,初始化对象
                    //3把这个对象指向这个空间 需要volatile修饰对象
                }
            }
        }
return lazy;
    }
//问题: 单线程下这个懒汉单例确实OK的,但是多线程并发就不行了
    //以下为代码测试 多线程并发操作
    //public static void main(String[] args){
    //    //10条线程并发测试
    //    for (int i = 1; i <= 10; i++) {
    //        new Thread(()->{
    //            Lazy.getInstance();
    //        }).start();
    //    }
    //    //如何解决这个问题呢?
    //    //获取对象实例的时候加synchronized锁
    //}
    //通过反射去破坏单例
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取懒汉单例实例
        Lazy lazy1 = Lazy.getInstance();
//空参构造器
        Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
//无视私有构造器
        declaredConstructor.setAccessible(true);
//通过反射创建对象
        Lazy lazy2 = declaredConstructor.newInstance();
//现在再测试懒汉单例模式是否被破坏
        System.out.println(lazy1);//com.wyh.single.Lazy@74a14482
        System.out.println(lazy2);//com.wyh.single.Lazy@1540e19d
        //很明显结果是不一样的 说明单例模式被反射破坏了
    }
}

mainok

mainok

com.wyh.single.Lazy@74a14482

com.wyh.single.Lazy@1540e19d

很明显值是不一样的 说明单例模式被反射破坏了,那么如何解决呢?

既然是通过破坏无参构造实现破坏单例模式

那么就可以再构造方法加锁并且判断对象是否已经被创建,如果对象已经被创建了,就进行错误提示

package com.wyh.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
 * @program: JUC
 * @description: 单例模式--懒汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:29
 **/
//懒汉模式相对于饿汉模式更加安全,会先判断是否需要使用资源,需要使用的话才进行加载,避免了资源浪费
public class Lazy {
//构造器私有
    private Lazy() {
//加锁 保证Lazy对象只能被创建一次
        synchronized (Lazy.class){
//如果单例对象不等于空,那么说明已 经被创建了
            if(lazy!=null){
                //错误提示
                throw new RuntimeException("不要视图使用反射破坏单例模式");
            }
        }
        System.out.println(Thread.currentThread().getName() + "ok");
    }
//加载对象 不会直接一上来就加载对象 而是会进行判断是否需要进行使用
    //为了防止指令重排 懒汉对象必须使用volatile进行修饰防止指令重排!
    private  static volatile Lazy lazy;
//获取实例方法
    public static Lazy getInstance(){
//双重检测锁模式的懒汉式单例 DCL懒汉式单例
        //判断对象不为空 不为空才会创建
        if(lazy==null){
//保证Lazy只有一个 锁的是class
            synchronized (Lazy.class){
if(lazy==null){
lazy=new Lazy(); //创建对象不是一个原子性操作
                    //创建分为三步
                    //1 分配内存空间
                    //2执行构造方法,初始化对象
                    //3把这个对象指向这个空间 需要volatile修饰对象
                }
            }
        }
return lazy;
    }
    //通过反射去破坏单例
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取懒汉单例实例
        Lazy lazy1 = Lazy.getInstance();
//空参构造器
        Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
//无视私有构造器
        declaredConstructor.setAccessible(true);
//通过反射创建对象
        Lazy lazy2 = declaredConstructor.newInstance();
//现在再测试懒汉单例模式是否被破坏
        System.out.println(lazy1);//com.wyh.single.Lazy@74a14482
        System.out.println(lazy2);//com.wyh.single.Lazy@1540e19d
        //很明显值是不一样的 说明单例模式被反射破坏了
        //如何解决呢?
        //既然是通过破坏无参构造实现破坏单例模式
        //那么就可以再构造方法加锁并且判断对象是否已经被创建,如果对象已经被创建了,就进行错误提示
    }
}

mainok

Exception in thread "main" java.lang.reflect.InvocationTargetException

       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

       at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)

       at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

       at java.lang.reflect.Constructor.newInstance(Constructor.java:423)

       at com.wyh.single.Lazy.main(Lazy.java:72)

Caused by: java.lang.RuntimeException: 不要视图使用反射破坏单例模式

       at com.wyh.single.Lazy.<init>(Lazy.java:23)

       ... 5 more

2 2个反射对象

我们只是通过加锁构造判断对象来结果反射带来的无参构造问题,现在两个对象对象都是通过反射来new的,该如何解决呢?

package com.wyh.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
 * @program: JUC
 * @description: 单例模式--懒汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:29
 **/
//懒汉模式相对于饿汉模式更加安全,会先判断是否需要使用资源,需要使用的话才进行加载,避免了资源浪费
public class Lazy {
//构造器私有
    private Lazy() {
//加锁 保证Lazy对象只能被创建一次
        synchronized (Lazy.class){
//如果单例对象不等于空,那么说明已 经被创建了
            if(lazy!=null){
//错误提示
                throw new RuntimeException("不要视图使用反射破坏单例模式");
            }
        }
        System.out.println(Thread.currentThread().getName() + "ok");
    }
//加载对象 不会直接一上来就加载对象 而是会进行判断是否需要进行使用
    //为了防止指令重排 懒汉对象必须使用volatile进行修饰防止指令重排!
    private  static volatile Lazy lazy;
//获取实例方法
    public static Lazy getInstance(){
//双重检测锁模式的懒汉式单例 DCL懒汉式单例
        //判断对象不为空 不为空才会创建
        if(lazy==null){
//保证Lazy只有一个 锁的是class
            synchronized (Lazy.class){
if(lazy==null){
lazy=new Lazy(); //创建对象不是一个原子性操作
                    //创建分为三步
                    //1 分配内存空间
                    //2执行构造方法,初始化对象
                    //3把这个对象指向这个空间 需要volatile修饰对象
                }
            }
        }
return lazy;
    }
    //通过反射去破坏单例
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取懒汉单例实例
        //Lazy lazy1 = Lazy.getInstance();
        //空参构造器
        Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
//无视私有构造器
        declaredConstructor.setAccessible(true);
//通过反射创建对象
        Lazy lazy1 = declaredConstructor.newInstance();
        Lazy lazy2 = declaredConstructor.newInstance();
//现在再测试懒汉单例模式是否被破坏
        System.out.println(lazy1);//com.wyh.single.Lazy@74a14482
        System.out.println(lazy2);//com.wyh.single.Lazy@1540e19d
        //很明显值是不一样的 说明单例模式被反射破坏了
        //如何解决呢?
        //既然是通过破坏无参构造实现破坏单例模式
        //那么就可以再构造方法加锁并且判断对象是否已经被创建,如果对象已经被创建了,就进行错误提示
    }
}

mainok

mainok

com.wyh.single.Lazy@74a14482

com.wyh.single.Lazy@1540e19d

可以通过定义标识的方法,判断是否非当前对象

package com.wyh.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
 * @program: JUC
 * @description: 单例模式--懒汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:29
 **/
//懒汉模式相对于饿汉模式更加安全,会先判断是否需要使用资源,需要使用的话才进行加载,避免了资源浪费
public class Lazy {
//标识符 判断是否非当前对象
    private static boolean flag=false;
//构造器私有
    private Lazy() {
//加锁 保证Lazy对象只能被创建一次
        synchronized (Lazy.class){
//如果标识符为false
            if(flag==false){
//把flag变为true
                flag = true;
            }else{
throw new RuntimeException("不要视图使用反射破坏单例模式");
            }
        }
        System.out.println(Thread.currentThread().getName() + "ok");
    }
//加载对象 不会直接一上来就加载对象 而是会进行判断是否需要进行使用
    //为了防止指令重排 懒汉对象必须使用volatile进行修饰防止指令重排!
    private  static volatile Lazy lazy;
//获取实例方法
    public static Lazy getInstance(){
//双重检测锁模式的懒汉式单例 DCL懒汉式单例
        //判断对象不为空 不为空才会创建
        if(lazy==null){
//保证Lazy只有一个 锁的是class
            synchronized (Lazy.class){
if(lazy==null){
lazy=new Lazy(); //创建对象不是一个原子性操作
                    //创建分为三步
                    //1 分配内存空间
                    //2执行构造方法,初始化对象
                    //3把这个对象指向这个空间 需要volatile修饰对象
                }
            }
        }
return lazy;
    }
//问题: 单线程下这个懒汉单例确实OK的,但是多线程并发就不行了
    //以下为代码测试 多线程并发操作
    //public static void main(String[] args){
    //    //10条线程并发测试
    //    for (int i = 1; i <= 10; i++) {
    //        new Thread(()->{
    //            Lazy.getInstance();
    //        }).start();
    //    }
    //    //如何解决这个问题呢?
    //    //获取对象实例的时候加synchronized锁
    //}
    //通过反射去破坏单例
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取懒汉单例实例
        //Lazy lazy1 = Lazy.getInstance();
        //空参构造器
        Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
//无视私有构造器
        declaredConstructor.setAccessible(true);
//通过反射创建对象
        Lazy lazy1 = declaredConstructor.newInstance();
        Lazy lazy2 = declaredConstructor.newInstance();
//现在再测试懒汉单例模式是否被破坏
        System.out.println(lazy1);//com.wyh.single.Lazy@74a14482
        System.out.println(lazy2);//com.wyh.single.Lazy@1540e19d
        //很明显值是不一样的 说明单例模式被反射破坏了
        //如何解决呢?
        //既然是通过破坏无参构造实现破坏单例模式
        //那么就可以再构造方法加锁并且判断对象是否已经被创建,如果对象已经被创建了,就进行错误提示
    }
}

mainok

Exception in thread "main" java.lang.reflect.InvocationTargetException

       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

       at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)

       at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

       at java.lang.reflect.Constructor.newInstance(Constructor.java:423)

       at com.wyh.single.Lazy.main(Lazy.java:78)

Caused by: java.lang.RuntimeException: 不要视图使用反射破坏单例模式

       at com.wyh.single.Lazy.<init>(Lazy.java:28)

       ... 5 more

3  破坏标识符 恶意修改

通过反射查到标识符,恶意进行修改,破坏单例

package com.wyh.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
 * @program: JUC
 * @description: 单例模式--懒汉模式
 * @author: 魏一鹤
 * @createDate: 2022-03-12 22:29
 **/
//懒汉模式相对于饿汉模式更加安全,会先判断是否需要使用资源,需要使用的话才进行加载,避免了资源浪费
public class Lazy {
//标识符 判断是否非当前对象
    private static boolean flag=false;
//构造器私有
    private Lazy() {
//加锁 保证Lazy对象只能被创建一次
        synchronized (Lazy.class){
//如果标识符为false
            if(flag==false){
//把flag变为true
                flag = true;
            }else{
throw new RuntimeException("不要试图使用反射破坏单例模式");
            }
        }
        System.out.println(Thread.currentThread().getName() + "ok");
    }
//加载对象 不会直接一上来就加载对象 而是会进行判断是否需要进行使用
    //为了防止指令重排 懒汉对象必须使用volatile进行修饰防止指令重排!
    private  static volatile Lazy lazy;
//获取实例方法
    public static Lazy getInstance(){
//双重检测锁模式的懒汉式单例 DCL懒汉式单例
        //判断对象不为空 不为空才会创建
        if(lazy==null){
//保证Lazy只有一个 锁的是class
            synchronized (Lazy.class){
if(lazy==null){
lazy=new Lazy(); //创建对象不是一个原子性操作
                    //创建分为三步
                    //1 分配内存空间
                    //2执行构造方法,初始化对象
                    //3把这个对象指向这个空间 需要volatile修饰对象
                }
            }
        }
return lazy;
    }
//问题: 单线程下这个懒汉单例确实OK的,但是多线程并发就不行了
    //以下为代码测试 多线程并发操作
    //public static void main(String[] args){
    //    //10条线程并发测试
    //    for (int i = 1; i <= 10; i++) {
    //        new Thread(()->{
    //            Lazy.getInstance();
    //        }).start();
    //    }
    //    //如何解决这个问题呢?
    //    //获取对象实例的时候加synchronized锁
    //}
    //通过反射去破坏单例
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//获取懒汉单例实例
        //Lazy lazy1 = Lazy.getInstance();
        //通过反射找到标识符
        Field flag = Lazy.class.getDeclaredField("flag");
//空参构造
        Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
//无视私有构造器
        declaredConstructor.setAccessible(true);
//通过反射创建对象
        Lazy lazy1 = declaredConstructor.newInstance();
//第一次创建完之后,恶意修改flag 破坏反射
        flag.set(lazy1,false);
        Lazy lazy2 = declaredConstructor.newInstance();
//现在再测试懒汉单例模式是否被破坏
        System.out.println(lazy1);//com.wyh.single.Lazy@1540e19d
        System.out.println(lazy2); //com.wyh.single.Lazy@677327b6
        //很明显值是不一样的 说明单例模式被反射破坏了
        //如何解决呢?
        //既然是通过破坏无参构造实现破坏单例模式
        //那么就可以再构造方法加锁并且判断对象是否已经被创建,如果对象已经被创建了,就进行错误提示
    }
}
目录
相关文章
|
2天前
|
设计模式 安全 Java
Java编程中的单例模式:理解与实践
【10月更文挑战第31天】在Java的世界里,单例模式是一种优雅的解决方案,它确保一个类只有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的实现方式、使用场景及其优缺点,同时提供代码示例以加深理解。无论你是Java新手还是有经验的开发者,掌握单例模式都将是你技能库中的宝贵财富。
|
13天前
|
设计模式 安全 Java
Java编程中的单例模式深入剖析
【10月更文挑战第21天】在Java的世界里,单例模式是设计模式中一个常见而又强大的存在。它确保了一个类只有一个实例,并提供一个全局访问点。本文将深入探讨如何正确实现单例模式,包括常见的实现方式、优缺点分析以及最佳实践,同时也会通过实际代码示例来加深理解。无论你是Java新手还是资深开发者,这篇文章都将为你提供宝贵的见解和技巧。
91 65
|
2天前
|
设计模式 安全 Java
Java编程中的单例模式深入解析
【10月更文挑战第31天】在编程世界中,设计模式就像是建筑中的蓝图,它们定义了解决常见问题的最佳实践。本文将通过浅显易懂的语言带你深入了解Java中广泛应用的单例模式,并展示如何实现它。
|
10天前
|
设计模式 SQL 安全
Java编程中的单例模式深入解析
【10月更文挑战第24天】在软件工程中,单例模式是设计模式的一种,它确保一个类只有一个实例,并提供一个全局访问点。本文将探讨如何在Java中使用单例模式,并分析其优缺点以及适用场景。
9 0
|
14天前
|
SQL 设计模式 Java
[Java]单例模式
本文介绍了单例模式的概念及其实现方式,包括饿汉式和懒汉式两种形式,并详细探讨了懒汉式中可能出现的线程安全问题及其解决方案,如锁方法、锁代码块和双重检查锁(DCL)。文章通过示例代码帮助读者更好地理解和应用单例模式。
22 0
|
2月前
|
设计模式 安全 Java
Java 编程中的设计模式:单例模式的深度解析
【9月更文挑战第22天】在Java的世界里,单例模式就像是一位老练的舞者,轻盈地穿梭在对象创建的舞台上。它确保了一个类仅有一个实例,并提供全局访问点。这不仅仅是代码优雅的体现,更是资源管理的高手。我们将一起探索单例模式的奥秘,从基础实现到高级应用,再到它与现代Java版本的舞蹈,让我们揭开单例模式的面纱,一探究竟。
38 11
|
22天前
|
设计模式 SQL 安全
【编程进阶知识】Java单例模式深度解析:饿汉式与懒汉式实现技巧
本文深入解析了Java单例模式中的饿汉式和懒汉式实现方法,包括它们的特点、实现代码和适用场景。通过静态常量、枚举类、静态代码块等方式实现饿汉式,通过非线程安全、同步方法、同步代码块、双重检查锁定和静态内部类等方式实现懒汉式。文章还对比了各种实现方式的优缺点,帮助读者在实际项目中做出更好的设计决策。
30 0
|
3月前
|
设计模式 存储 负载均衡
【五】设计模式~~~创建型模式~~~单例模式(Java)
文章详细介绍了单例模式(Singleton Pattern),这是一种确保一个类只有一个实例,并提供全局访问点的设计模式。文中通过Windows任务管理器的例子阐述了单例模式的动机,解释了如何通过私有构造函数、静态私有成员变量和公有静态方法实现单例模式。接着,通过负载均衡器的案例展示了单例模式的应用,并讨论了单例模式的优点、缺点以及适用场景。最后,文章还探讨了饿汉式和懒汉式单例的实现方式及其比较。
【五】设计模式~~~创建型模式~~~单例模式(Java)
|
2月前
|
设计模式 Java 安全
Java设计模式-单例模式(2)
Java设计模式-单例模式(2)
|
3月前
|
设计模式 安全 Java
Java 单例模式,背后有着何种不为人知的秘密?开启探索之旅,寻找答案!
【8月更文挑战第30天】单例模式确保一个类只有一个实例并提供全局访问点,适用于需全局共享的宝贵资源如数据库连接池、日志记录器等。Java中有多种单例模式实现,包括饿汉式、懒汉式、同步方法和双重检查锁定。饿汉式在类加载时创建实例,懒汉式则在首次调用时创建,后者在多线程环境下需使用同步机制保证线程安全。单例模式有助于提高代码的可维护性和扩展性,应根据需求选择合适实现方式。
33 1