23种设计模式——单例模式

定义

单例模式的定义是:确保一个类只有一个实例,并提供全局访问点。

优点

  • 全局唯一性:保证一个类只有一个实例,避免了不必要的内存消耗。
  • 全局访问点:提供一个全局访问的接口,方便其他代码使用。

缺点

  • 可能引起性能问题:在高并发环境下,多个线程同时请求单例对象可能会引起性能瓶颈。
  • 对拓展性不好单例类只能有一个对象实例。但如果未来改需求了,需要创建两个或多个实例,就需要对代码有比较大的改动。
  • 不支持有参构造:单例不支持有参数的构造函数,如果想要传递参数,只能在 getInstance 方法中添加参数,或者定义方法传递参数。

应用场景

  • 资源共享:例如配置文件、日志对象等需要共享的资源。
  • 线程池、连接池:确保全局只有一个实例,避免资源竞争和浪费。
  • 日志对象:避免在多个地方创建不同的日志对象,统一管理。
  • 缓存:保证缓存的一致性和有效性。

为什么要使用单例

使用单例模式的主要目的是确保一个进程只有一个实例,避免不必要的资源浪费,同时提供一个全局访问点方便其他代码使用。在需要全局唯一性、全局访问点或者共享资源的情况下,单例模式是一个很好的选择。

作用域与范围

单例模式的作用域是全局的,即在整个应用程序中只有一个实例。这样可以确保各个模块之间共享同一个实例,避免了资源的重复创建和管理。

单例是如何保证唯一的

单例模式保证实例的唯一性是通过以下方式实现的:

  1. 私有化构造方法:单例类的构造方法被私有化,禁止外部直接创建实例。
  2. 静态方法返回实例:通过一个静态方法返回单例对象,在该方法内部进行实例的创建和管理。
  3. 线程安全控制:针对多线程环境,通过加锁等方式来保证实例的唯一性和线程安全性。

单例创建方式

1、饿汉式
ublic class HungrySingletonPattern implements Serializable {
    private static final HungrySingletonPattern instance = new HungrySingletonPattern();

    private static boolean flag = false;

    private HungrySingletonPattern() {
        //线程安全
        synchronized ( HungrySingletonPattern.class) {
            if (flag) {
                throw new RuntimeException("单例模式不允许多个实例");
            }
            flag = true;
        }
    }

    public static HungrySingletonPattern getInstance() {
        return instance;
    }

    //反序列化时,会自动调用该方法
    @Serial
    public Object readResolve() {
        return instance;
    }

    //    //静态代码块创建
    //
    //    static {
    //        instance = new LazySingletonPattern();
    //    }
    //
    //    public static LazySingletonPattern getInstance() {
    //        return instance;
    //    }
}
2、懒汉式
public class LazySingletonPattern implements Serializable {

     private static boolean flag = false;
    
    //1.私有化构造方法
    private LazySingletonPattern() {
         //线程安全
        synchronized ( HungrySingletonPattern.class) {
            if (flag) {
                throw new RuntimeException("单例模式不允许多个实例");
            }
            flag = true;
        }
    }

    //2.私有化静态变量
    //volatile关键字修饰,防止指令重排序,避免多线程下,对象创建失败
    private static volatile LazySingletonPattern instance;

    //3.提供公共的静态方法
    public static LazySingletonPattern getInstance() {
        //1.判断是否为空
        if (instance == null) {
            synchronized (LazySingletonPattern.class){
                if (instance == null) {
                    //2.创建对象
                    instance = new LazySingletonPattern();
                }
            }
        }
        return instance;
    }

    //反序列化时,会自动调用该方法
    @Serial
    public Object readResolve() {
        return instance;
    }
    
    //静态内部类加载,JVM在加载外部类时,是不会加载内部类的,只有当调用静态内部类中的方法时,才会加载静态内部类,并且创建静态内部类对象,
    // 静态内部类加载时,会自动加载外部类,并且创建静态内部类对象
    //    private static class LazySingletonPatternHolder {
    //        private static final LazySingletonPattern INSTANCE = new LazySingletonPattern();
    //    }
    //
    //    public static LazySingletonPattern getInstance() {
    //        return LazySingletonPatternHolder.INSTANCE;
    //    }
}

3、枚举式
public enum EnumSingletonPattern {
    INSTANCE;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值