Singleton(单例模式)

阅读前须知:原文博客请访问 merengues.top

单例模式

单例模式(singleton)保证一个类只有一个实例,并且提供了一个访问全局访问点。

适用性
  • 当类只能有一个实例而且客户可以从一个访问点访问它时。
  • 当这个实例应该通过子类化可扩展的,并且客户无须更改代码就能使用拓展的实例。
结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H6ZBLhXS-1599130399565)(C:\Users\26813\Desktop\QQ截图20200817100353.png)]

效果
  • 对唯一实例的受控访问 Singleton可以严格控制用户怎样以及何时访问它。
  • 缩小名字空间 Singleton可以避免全局变量污染命名空间。
  • 允许对操作和表示的精化 Singleton类可以有子类,可以用所需要类的实例在运行时配置应用。
  • 允许可变数目的实例
类别
懒汉式

使用时创建实例。

优点:第一次调用的时候才初始化,避免内存浪费。

缺点:必须加锁才能保证线程安全,加锁则会影响性能。

饿汉式

类加载时就创建实例。

优点:不用加锁就能保证线程安全,执行效率高。

缺点:类加载就初始化,内存浪费。

实现
懒汉式

1)示例1

public class Singleton{
    private static Singleton instance;
    
    private Singleton(){};
    
    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

线程不安全,避免使用。

2)示例2

public class Singleton{
    private static Singleton instance;
    
    private Singleton(){};
    
    public static synchronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

线程同步,线程安全,效率低,避免使用。

3)示例3

public class Singleton{
    private static Singleton instance;
    
    private Singleton(){};
    
    public static Singleton getInstance(){
        if(instance == null){
            synchronized(Singleton.class){
                instance = new Singleton();
            }
        }
        return instance;
    }
}

线程不安全,会产生多个实例,不可用

饿汉式

1)示例1

public class Singleton{
    private static Singleton instance = new Singleton;
    
    private Singleton(){};
    
    public static Singleton getInstance(){
        return instance;
    }
}

2)示例2

public class Singleton{
    private static Singleton instance = null;
    
    static{
        instance = new Singleton;
    }
    
    private Singleton(){};
    
    public static Singleton getInstance(){
        return instance;
    }
}

无线程安全问题,影响系统效率,不推荐

双重校验锁
public class Singleton{
    private static Singleton instance;
    
    private Singleton(){};
    
    public static Singleton getInstance(){
        if(instance == null){
            synchronized(Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

双重校验锁,线程安全,懒加载,推荐使用

静态内部类
public class Singleton{
    
    private static class SingletonHolder{
        private static final Singleton INSTANCE = new Singleton();
    }
    
    private Singleton(){}
    
    public static final Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

静态内部类,线程安全,主动调用才示例化,懒加载效率高,推荐使用

枚举
public enum Singleton{
    INSTANCE;
    
    private Singleton(){};
    
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

枚举类型,无线程安全问题,避免序列化创建新实例,使用少;

注意事项
  • 考虑多线程问题
  • 如果类可序列化,考虑反序列化生成多个实例问题,解决方法如下:
private Object readResolve() throw ObjectStreamException{
    /**
    *在类中添加readResolve方法返回单例对象
    **/
    return instance;
}
  • 反射会破坏单例模式,避免用反射创建单例对象:
private Singleton(){
    if(instance != null){
        throw new RuntimeException("禁止反射创建单例对象");
    }
}
    /**
    *在类中添加readResolve方法返回单例对象
    **/
    return instance;
}
  • 反射会破坏单例模式,避免用反射创建单例对象:
private Singleton(){
    if(instance != null){
        throw new RuntimeException("禁止反射创建单例对象");
    }
}
  • 19
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
单例模式Singleton Pattern)是一种创建型模式,它保证一个类只有一个实例,并提供一个全局访问点。单例模式通常用于控制某些资源的访问权限,或者在整个系统中只需要一个共享资源的情况下使用。 在单例模式中,类的构造函数必须私有化,这样外部就不能直接实例化该类。同时,类中需要定义一个静态方法,用于获取该类唯一的实例。在第一次调用该方法时,会创建一个实例,并将其保存下来。以后每次调用该方法时,都会返回同一个实例。 例如,下面的代码演示了如何在C++中实现单例模式: ```c++ class Singleton { public: static Singleton& getInstance() { static Singleton instance; // 延迟初始化,保证线程安全 return instance; } private: Singleton() {} // 将构造函数私有化,防止外部实例化 Singleton(const Singleton&) = delete; // 禁止拷贝构造函数 Singleton& operator=(const Singleton&) = delete; // 禁止赋值运算符 }; int main() { Singleton& s1 = Singleton::getInstance(); Singleton& s2 = Singleton::getInstance(); std::cout << std::boolalpha << (&s1 == &s2) << std::endl; // 输出:true return 0; } ``` 在这个例子中,我们定义了一个名为Singleton的类,并将其构造函数私有化,防止外部实例化。同时,我们定义了一个静态方法getInstance,用于获取该类唯一的实例。在getInstance方法中,我们使用了静态局部变量的方式来延迟初始化,保证线程安全。最后,在main函数中,我们多次调用getInstance方法,每次调用都会返回同一个实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值