定义:指一个类只有一个实例,且能自行创建这个实例的一种模式.例如,windows中只能打开一个任务管理器,这样可以避免因打开多个任务管理器而造成内存资源浪费,而出现各个窗口显示内容的不一致错误. 单例模式特点: 1)单例只有一个实例对象 2)该单例对象必须由单例类自行创建 3)单例类对外提供一个访问单例的全局点 单例的优点: 1)单例例模式1可以保证内存中只有一个实例,减少了内存的消耗. 2)可以避免对资源的多重占用 3)单例模式设置全局访问点,可以优化和共享资源的访问 单例的缺点: 1)单例模式一般没有借口,扩展困难,如果要扩展,则修改了原来的代码,没有第二种途径违背开闭原则 2)在并发测试中,单例模式不利于代码调试.在调试过程中,如果单例中代码还没有执行完,也不能模拟生成一个新的对象. 3)单例模式通常写在一个类中,如果功能设计不合理,和容易违背单一职责原则 单例的应用场景: 1)需要频繁创建一些类,使用单例模式可以降低系统的内存压力,减少gc 2)某类只要求生成一个对象的时候,比如一个班的班长,每个人的身份证号 3)某类创建实例需要消耗资源过多,或者实例化消耗较长,且经常使用 4)频繁访问数据库或者文件的对象 5)默写类需要频繁实例化,而创建的对象又频繁销毁的时候,不如多线程的线程池,网络的连接池 6)对于一些控制硬件级别的操作,或者从协同上讲是单一控制的操作,如果有多个实例,则系统会乱套 7)当对象需要被共享的场合.由于单例模式只允许创建一个对象,共享对象可以节省内存,并加快对象访问速度.比如web中的配置对象,数据库连接池
//饿汉式(静态变量) class Singleton { //1. 构造器私有化, 外部能new private Singleton() { } //2.本类内部创建对象实例 private final static Singleton instance = new Singleton(); //3. 提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
//饿汉式(静态变量) class Singleton { //1. 构造器私有化, 外部能new private Singleton() { } //2.本类内部创建对象实例 private static Singleton instance; static { // 在静态代码块中,创建单例对象 instance = new Singleton(); } //3. 提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
// 懒汉式(线程安全,同步方法) class Singleton { private static volatile Singleton instance; private Singleton() {} //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题 //同时保证了效率, 推荐使用 public static Singleton getInstance() { if(instance == null) { synchronized (Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; } }
// 静态内部类完成, 推荐使用 class Singleton { private static volatile Singleton instance; //构造器私有化 private Singleton() {} //写一个静态内部类,该类中有一个静态属性 Singleton private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE public static synchronized Singleton getInstance() { return SingletonInstance.INSTANCE; } }
//使用枚举,可以实现单例, 推荐 enum Singleton { INSTANCE; //属性 public void sayOK() { System.out.println("ok~"); } }
线程安全,枚举会编译成静态内部类)
//使用枚举,可以实现单例, 推荐 enum Singleton { INSTANCE; //属性 public void sayOK() { System.out.println("ok~"); } }