单例模式

单例模式

定义

Ensure a class has only one instance, and provide a global point of access to it.

通用类图是:

在这里插入图片描述

通用代码是:

public class Singleton {
    private static final Singleton singleton = new Singleton();
    
    private Singleton(){}
    public static Singleton getSingleton(){
        return singleton;
    }
}

单例模式应用

优点
  • 减少内存开支,特别是对象需要频繁的创建、销毁时
  • 减少系统性能的开销,当对象的产生需要比较多的资源,可以在启动时直接产生一个单例对象的方式来解决
  • 避免对资源的多重占用
  • 可以在系统设置全局的访问点,优化和共享资源。。。
缺点
  • 一般没有接口,扩展困难
  • 对测试时不利的
  • 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心它是否是单例的,是不是单例取决于环境,单例模式把“要单例”和业务逻辑融合在一个类中了。
使用场景
  • 要求生成唯一序列号的环境
  • 在整个项目中需要一个共享访问点或共享数据,例如一个Web页面的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保线程安全即可
  • 创建一个对象需要消耗较多的资源,如访问IO和数据库等
  • 需要定义大量的静态常量和静态方法的环境,可以采用单例模式
注意问题
  • 线程安全问题
  • 考虑对象的赋值情况,对象复制是不调用类的构造函数的

多种单例实现

  1. 懒汉式(延迟加载)

    public class Singleton{
        private static Singleton singleton;
    
        private Singleton() {
        }
    
        public synchronized static Single newInstance() {
            if (singleton== null) {
                singleton= new Singleton();
            }
            return singleton;
        }
    }
    

    标准的单例模式,通过newInstance里面的判断来进行延迟加载单例对象,这里加了synchronized关键字可以避免多线程问题,但会影响程序性能。

  2. 饿汉式(贪婪加载)

    public class Singleton {
        private static Singleton singleton= new Singleton();
    
        private singleton() {
        }
    
        public static Singleton newInstance() {
            return singleton;
        }
    }
    

    在单例对象声明的时候就直接初始化对象,可以避免多线程问题,但是如果对象初始化比较复杂,会导致程序初始化缓慢。

  3. 双重检查加锁

    public class Singleton {
        private volatile static Singleton singleton;
    
        private Singleton() {
        }
    
        public static Singleton newInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    

    这个是懒汉形式的加强版,将synchronized关键字移到了newInstance方法里面,同时将singleton对象加上volatile关键字,这种方式既可以避免多线程问题,又不会降低程序的性能。但volatile关键字也有一些性能问题,不建议大量使用。

  4. 内部静态类

    public class Singleton {
        private static class SingletonHolder {
            private static Singleton singleton = new Singleton();
        }
    
        private Singleton() {
        }
    
        public static Singleton newInstance() {
            return SingletonHolder.singleton;
        }
    }
    

    通过内部类的机制使得单例对象可以延迟加载,同时内部类相当于是外部类的静态部分,所以可以通过jvm来保证其线程安全。这种形式比较推荐。

  5. 枚举类

    public enum Singleton {
        singleton
    }
    

的机制使得单例对象可以延迟加载,同时内部类相当于是外部类的静态部分,所以可以通过jvm来保证其线程安全。这种形式比较推荐。

  1. 枚举类

    public enum Singleton {
        singleton
    }
    

    最推荐的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值