设计模式--单例模式--懒汉饿汉

单例模式

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

结构图

Singleton类,定义一个负责GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例。

java 复制代码
public class Singleton {
    
    private static Singleton instatnce;

    private Singleton() {   // 无参构造私有化,防止外部new对象
    }
    
    // 得到Singleton的实例,唯一的途径
    public static Singleton getInstance() { 
        if (instatnce == null) {
            instatnce = new Singleton();
        }
        return instatnce;
    }
}

客户端

java 复制代码
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();

if (s1 == s2) {
    System.out.println("对象相同");
}

多线程

另外还需要注意一些细节,比如,多线程的程序中,多个线程同时访问Singleton类,调用getInstance()方法时,会可能创建多个实例。我们需要加一些锁。

java 复制代码
public synchronized static Singleton getInstance() {
    if (instatnce == null) {
        instatnce = new Singleton();
    }
    return instatnce;
}

使用synchronized关键字锁住此方法,使得此方法在同一个时间点只有一个线程能进入访问。

这样看起来也没有问题,但是会有一个性能的问题:每次调用此方法的时候都需要锁,但其实我们只需要在创建instance 的时候让一个线程去创建就行。那么再改造一下。

双重锁定

java 复制代码
public class Singleton {

    private volatile static Singleton instatnce;

    private Singleton() {   // 无参构造私有化,防止外部new对象
    }

    // 得到Singleton的实例,唯一的途径
    public static Singleton getInstance() {
        if (instatnce == null) {
            synchronized (Singleton.class){	// 防止多个线程进入创建实例
                if (instatnce == null) {
                    instatnce = new Singleton();
                }
            }
        }
        return instatnce;
    }
}

使用volatile关键字,当synchronized变量被初始化成Singleton时,多个线程能正确处理synchronized变量。

synchronized 代码块儿中,还需要再加一层对instance的判断,因为当多个线程访问此方法时,它们都是通过了第一层instance==null的判断的,里面再加一层判断,防止后进入的线程又一次去创建实例。

静态初始化

在实际应用中,上面的做法都能应付自如。不过为了确保实例唯一,还是会带来很大的性能代价。对于性能要求很高的程序,建议还是采用静态初始化,也就是饿汉模式。

java 复制代码
public class Singleton {

    private static Singleton instatnce = new Singleton();

    private Singleton() {   // 无参构造私有化,防止外部new对象
    }

    // 得到Singleton的实例,唯一的途径
    public static Singleton getInstance() {
        return instatnce;
    }
}

这种静态初始化的方式是在自己被加载时就将自己实例化,所以被形象称之为饿汉式单例类。

要在第一次被引用时,才将自己实例化,则是被称之为懒汉式单例类。

大多数情况都是选择使用饿汉模式单例类,实际按项目需求做出选择。

相关推荐
未来可期LJ2 小时前
【C++ 设计模式】单例模式的两种懒汉式和饿汉式
c++·单例模式·设计模式
丶白泽9 小时前
重修设计模式-结构型-组合模式
设计模式·组合模式
yunhuibin10 小时前
ffmpeg面向对象——参数配置秘密探索及其设计模式
学习·设计模式·ffmpeg
_祝你今天愉快11 小时前
技术成神之路:设计模式(十四)享元模式
java·设计模式
蔚一12 小时前
Java设计模式—面向对象设计原则(三) -----> 依赖倒转原则DIP(完整详解,附有代码+案例)
java·开发语言·设计模式·intellij-idea·依赖倒置原则
丶白泽14 小时前
重修设计模式-概览
java·设计模式
java_heartLake16 小时前
设计模式之建造者模式
java·设计模式·建造者模式
G皮T16 小时前
【设计模式】创建型模式(四):建造者模式
java·设计模式·编程·建造者模式·builder·建造者
战神刘玉栋17 小时前
《程序猿之设计模式实战 · 观察者模式》
python·观察者模式·设计模式
nakyoooooo18 小时前
【设计模式】工厂模式、单例模式、观察者模式、发布订阅模式
观察者模式·单例模式·设计模式