前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一篇通俗易懂的文章让你彻底了解设计模式中的单例模式

一篇通俗易懂的文章让你彻底了解设计模式中的单例模式

作者头像
@派大星
发布2023-06-28 14:08:40
发布2023-06-28 14:08:40
23200
代码可运行
举报
文章被收录于专栏:码上遇见你码上遇见你
运行总次数:0
代码可运行

之前给大家讲了关于设计模式的七大原则,这一次给大家带来了设计模式中的单例模式,以后会将23种设计模式一一为大家准备好。接下来让我们来看看单例模式吧。

概念:

就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法静态方法。

单例模式一共有8中方式

想必这是大家第一次听到有这么多吧,不要慌,其实都是大同小异。

请看

  1. 饿汉式(静态常量)
  2. 饿汉式(静态代码块)
  3. 懒汉式(线程不安全)
  4. 懒汉式(线程安全,同步方法)
  5. 懒汉式(线程安全,同步代码块)
  6. 双重检查
  7. 静态内部类
  8. 枚举

1.饿汉式(静态常量)

代码语言:javascript
代码运行次数:0
运行
复制
class Singleton{
    //1.构造器私有化,外部无法new
    private Singleton(){
    }
    //2.本类内部创建对象实例
    private final static Singleton instance = new Singleton();
    //3.对外提供一个共有的静态方法 返回实例对象
    public static Singleton getInstance(){
        return instance;
    }
}

优点:比较简单,避免了线程同步问题,但是在类装载的时候就完成了实例化,没有达到lazying loading,如果从未使用过该实例则有可能造成内存浪费 该方法在基于classloader机制避免了线程安全问题

2.饿汉式(静态代码块)

代码语言:javascript
代码运行次数:0
运行
复制
class Singleton{
    //1. 构造私有化,外部无法new
    private Singleton(){
        
    }
    //2. 本类内部创建实例
    private static Singleton instance;
    static{//静态代码块中创建单例对象
        instance = new Singleton();
    }
    //3. 提供一个共有的静态方法,返回实例对象
    public static Singleton getInstance(){
        return instance;
    }
}

这种与上面的方法类似(静态常量),只不过将实例化过程放在了静态代码块中。优缺点一样和上面方法。

3.懒汉式(线程安全)

代码语言:javascript
代码运行次数:0
运行
复制
class Singleton{
    private static Singleton instance;
    
    private Singleton(){}
    
    // 提供一个静态的公有方法,当使用到方法时,才去创建instance
    // 即懒汉式
    public static Singleton getInstance(){
        if(instance ==null){
            instance = new Singleton();
        }
        return instance;
    }
}

优缺点: 起到了Lazying Loading的效果,但是只能在单线程下使用 多线程下if(instance ==null) 有可能造成一个线程正在执行,对象还未创建成功,另外一个线程也通过了这个判断

4.懒汉式(线程安全,同步方法)

代码语言:javascript
代码运行次数:0
运行
复制
class Singleton{
    // 本地内部创建静态实例
    private static Singleton instance;
    // 私有化构造方法
    private Singleton(){}
    // 提供一个静态的共有方法,加入同步处理的代码,解决线程安全问题;
    // 懒汉式
    public static sychronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

优缺点: 解决了线程安全问题。但是效率太低了,没个线程想要获得类的实例的时候,执行getInstance()方法都要进行同步,而这个方法只执行一次实例化就够了,后面再想要获取实例直接return即可看,方法进行同步效率太低 不推荐使用

5.懒汉式(同步代码块,线程不安全)

代码语言:javascript
代码运行次数:0
运行
复制
class Singleton {
    // 本地内部创建静态实例
    private static Singleton singleton;
    // 私有化构造方法
    private Singleton(){}
    // 提供一个共有的静态方法 加入同步代码块
    prublic static Singleton getInstance(){
        if(instancell = null){
            sychronized(Singleton.class){
                singleton = new Singleton();
            }
        }
        return singleton;
    }
}

线程不安全线上环境不可使用

6.💡双重检查

代码语言:javascript
代码运行次数:0
运行
复制
class Singleton{
    // 本地内部创建内部实例
    private static Singleton instance;
    // 私有化构造方法
    //提供一个共有的静态方法,加入双重检查代码机制,避免线程安全问题,同时解决懒加载问题
    // 保证了安全性  提高了效率
    public static Singleton getInstance(){
        if(instance == null){
            sychronized(Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

优缺点: Double Check 概念是多线程中中开发常用到的,我们在这里就进行了两次instance == null判断,这样就可以保证线程安全了,并且实例化代码只执行一次,下次再访问直接return了,避免反复进行方法同步。 线程安全、延迟加载、效率较高推荐使用

7.💡静态内部类

代码语言:javascript
代码运行次数:0
运行
复制
class Singleton{
    // 本地内部创建静态实例
    private static Singleton instance;
    // 构造器私有化
    private Singleton(){}
    // 写一个静态内部类,该类中有一个静态属性Singleton
    private static class SingletonInstance{
        private static Singleton INSTANCE = new Singelton();
    }
    // 提供一个共有的静态方法 直接返回SingletonInstance.INSTANCE
    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

优缺点: 这种方式采用类加载的方式保证了初始化实例时只有一个线程, 静态内部类在Singleton类装载的时候不会立即初始化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化 类的静态属性只会在第一次加载类的时候初始化i,所以在这里JVM保证了线程的安全性 优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高

8.💡枚举

代码语言:javascript
代码运行次数:0
运行
复制
enum Singleton{
    INSTANCE;// 属性
    public sayHello(){
        System.out.println("~ok~")
    }
}

优缺点: 借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。 推荐使用

JDK中java.lang.Runtime就是经典的单例模式(饿汉式)。

总结:

  • 单例的使用场景:需要频繁的进行创建和销毁对象。创建对象时消耗过多资源(即重量级对象),但又经常使用到的对象。工具类。频繁访问数据库或文件的对象,(数据源、session工厂等)。
  • 想要获取单例类的时候,要使用对应获取对象的方法,而不是new

好了到这里,单例模式的所有情况就已经讲完了。小伙伴们是否有所收获。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上遇见你 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.饿汉式(静态常量)
  • 2.饿汉式(静态代码块)
  • 3.懒汉式(线程安全)
  • 4.懒汉式(线程安全,同步方法)
  • 5.懒汉式(同步代码块,线程不安全)
  • 6.💡双重检查
  • 7.💡静态内部类
  • 8.💡枚举
  • 总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档