设计模式之单例模式

确保一个类在任何情况下都只有一个实例,并提供一个全局访问点

设计模式之单例模式_第1张图片

结构

单例类:只能创建一个实例的类

访问类:使用单例类的类

优缺点

优点:

        1、在内存里只有一个实例,减少了内存的开销

        2、避免对资源的多重占用

缺点:

        没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

特点

        1.单例类只能有一个实例

        2.单例类必须自己创建自己的唯一实例

        3.单例类必须给所有其他对象提供这一实例

使用场景

        1.有频繁的实例化后又销毁的情况,适合考虑使用单例模式,如记录日志的log对象

        2.创建对象需要消耗过多的系统资源,但又经常用到的资源,如数据库连接

创建模式

饿汉式

在该类初始化的时候就创建实例对象,线程是安全的

public class Singleton {  
    // 在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快  
    private static Singleton instance = new Singleton();  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        return instance;  
    }  
}

        饿汉式单例模式的优点是线程安全且效率高。由于实例在类加载时就创建了,所以获取对象的速度快。此外,由于构造函数是私有的,外部无法创建实例,因此可以保证只有一个实例

缺点:

        饿汉式单例模式的缺点是可能会造成内存空间的浪费。如果该实例需要消耗大量的内存,且在程序的生命周期内可能不会使用到这个实例,那么就会造成内存空间的浪费

懒汉式

首次使用单例实例的时候创建,之后使用时再判断单例实例是否已创建,如果没有则创建实例

public class Singleton {  
    // 私有静态变量,用于保存单例对象  
    private static Singleton instance;  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 在第一次使用时,通过静态代码块创建实例  
    private static void initializeInstance() {  
        instance = new Singleton();  
    }  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        if (instance == null) {  
            initializeInstance();  
        }  
        return instance;  
    }  
}

instance变量在第一次调用getInstance()方法时才创建,因此线程是不安全的。为了实现线程安全,可以使用双重检查锁定、静态初始化块、枚举方式

优点:

        只有在需要使用实例时才创建。这可以节省内存空间,特别是对于那些在程序生命周期中不一定需要的实例

双重检查锁定

public class Singleton {  
    // 使用volatile关键字,确保该变量在多线程环境下保持可见性  
    private volatile static Singleton instance;  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 在第一次使用时,通过静态代码块创建实例  
    private static void initializeInstance() {  
        instance = new Singleton();  
    }  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        // 第一次检查,如果instance不为null,说明实例已经被初始化,直接返回实例即可  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                // 第二次检查,如果instance为null,说明实例还没有被初始化,需要进入同步块进行初始化  
                if (instance == null) {  
                    instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}

instance变量使用volatile关键字修饰,以确保在多线程环境下保持可见性。双重检查锁定通过两次检查instance变量的值是否为null来实现线程安全

静态初始化块

public class Singleton {  
    // 私有静态变量,用于保存单例对象  
    private static Singleton instance;  
  
    // 私有化构造函数,防止外部创建对象  
    private Singleton(){}  
  
    // 使用静态初始化块来创建实例  
    static {  
        instance = new Singleton();  
    }  
  
    // 提供一个全局访问点  
    public static Singleton getInstance(){  
        return instance;  
    }  
}

instance变量在类加载时创建实例,因此它是线程安全的。

优点:避免了在第一次调用getInstance()方法时进行同步的开销;线程安全的,可以确保只创建一个实例

缺点:会造成类加载的开销

枚举方式

枚举类实现单例模式是极力推荐的单例实现模式,因为枚举是线程安全的,并且只会装载一次,枚举类是所有单例类实现中唯一不会被破坏的单例模式

public enum Singleton {  
    INSTANCE;  
  
    // 单例对象  
    private Singleton instance;  
  
    // 私有方法,用于创建实例  
    private void createInstance() {  
        instance = new Singleton();  
    }  
  
    // 公共方法,用于获取实例  
    public Singleton getInstance() {  
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    createInstance();  
                }  
            }  
        }  
        return instance;  
    }  
}

   instance变量在枚举类型被加载时创建实例,因此它是线程安全的。枚举类型在Java中是线程安全的,并且只有一个实例。getInstance()方法用于获取实例,它首先检查instance变量是否为null,如果是null,则进入同步块,再次检查instance变量是否为null,如果是null,则创建一个新的实例

优点:具有更高的性能和更少的内存占用;使用枚举实现的单例模式更加简单和安全

缺点:只能创建单一的实例,无法实现多个实例的创建和管理

你可能感兴趣的:(设计模式,设计模式,单例模式,java)