计模式之单件模式(单例模式)

单件模式是最简单的设计模式啦!(窝感觉~~)

有一些对象我们只需要一个,例如:线程池(threadpool),缓存(cache),充当打印机,显卡等设备的驱动程序的对象。

这些类对象只能有一个实例,多了会出现一些问题。

 

全局变量缺点:必须在一开始就创建对象,浪费资源。

 

只创建一个对象的方法:首先将构造函数私有,这样这个类就不会随意的创建了。然后为类创建一个产生实例变量的方法。

public class MyClass {
    private MyClass() {}
    public static MyClass getIntance() {
        return new MyClass();
    }
}    

单件模式的实现:

复制代码
public class Singleton {
    
    private static Singleton uniqueSingleton; 
    
    private Singleton() { }
    
    public static Singleton getInstance() {
        if (uniqueSingleton == null) {
            uniqueSingleton = new Singleton();
        }
        return uniqueSingleton;
    }
    
    
}
复制代码

 

如果不需要这个实例,它就永远不会被产生,这就是“延迟实例化”(lazy-instantiaze)

 

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

 

但是在多线程情况下,会产生一些问题,如下图情况:

呀~~产生了两个对象!

于是在多线程的时候

需要把getInstance()函数变成同步方法啦

public static synchronized Singleton getInstance() {
    if (uniqueSingleton == null) {
        uniqueSingleton = new Singleton();
    }
    return uniqueSingleton;
}

 

但是……同步会降低性能……

1.如果getInstance()方法的性能对应用程序不是很关键,就这样就可以了。

2.如果程序总是创建并使用单件实例,或者在创建或运行时方面的负担不太繁重,可以一开始就创建实例。

复制代码
public class Singleton {
    
    private static Singleton uniqueSingleton = new Singleton(); 
    
    private Singleton() { }
    
    public static Singleton getInstance() {
        return uniqueSingleton;
    }
    
}
复制代码

3.用双重加锁,在getInstance()中减少使用同步

复制代码
public class Singleton {
    
    private volatile static Singleton uniqueSingleton;    // volatile关键字确保  当uniqueSingleton被初始化后
                                                          // 多个线程正确的处理uniqueSingleton变量
    
    private Singleton() { }
    
    public static Singleton getInstance() {
        if (uniqueSingleton == null) {                    // 检查实例  如果不存在就进入同步区
            synchronized (Singleton.class) {
                if (uniqueSingleton == null) {            // 进入区块后  在检查一次  如果仍然是null 才创建实例
                    uniqueSingleton = new Singleton();    // 注意:只有第一次才彻底执行这里的代码
                }
            }
        }
        return uniqueSingleton;
    }
    
}
复制代码

 

4. 通过枚举实现单例模式

通过内部静态enum的方法来实现,因为JVM会保证enum不能被反射并且构造器方法只执行一次。

复制代码
public class EnumSingleton {
    private EnumSingleton() {}
    
    public static EnumSingleton getInstance(){
        return Singleton.INSTANCE.getInstance();
    }
    
    private static enum Singleton{
        INSTANCE;
        
        private EnumSingleton singleton;
        //JVM会保证此方法绝对只调用一次
        private Singleton(){
            singleton = new EnumSingleton();
        }
        public EnumSingleton getInstance() {
            return singleton;
        }
    }
}
复制代码

 

posted @   我不吃饼干呀  阅读(272)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2016-03-11 KM算法详解+模板
点击右上角即可分享
微信分享提示