单例模式(Singleton Pattern)
是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
单例模式:确保整个系统中只有一个对象。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
我们可以通过这种方式直接访问,不需要实例化该类的对象。什么时候创建自己的对象是自己决定。
什么时候创建分为两种。懒汉式和饿汉式。
package com.shiro.springbootshiro.Singleton;
/**
* 作用:饿汉式
* 类加载时就初始化,浪费内存。
* 是否多线程安全:是安全的。不用加锁。执行效率会高。
* 是否lazy初始化:否
* 第一次类创建的同时就实例化一个静态对象。以后不管使用不使用,都会占内存。
* 在第一次调用的时候速度也会比较快,因为资源已经被加载。
*/
public class SingletonEH {
private static SingletonEH instance=new SingletonEH();
// 为什么是私有的。 限制产生多个对象
private SingletonEH(){}
public static SingletonEH getInstance() {
return instance;
}
}
package com.shiro.springbootshiro.Singleton; /** * 作用:懒汉式 * 是否多线程安全:否。要确定线程安全,要加上锁。 * 是否lazy初始化:是 * 会延迟加载,如果没有使用到,就一直不创建。第一次调用的时候才会初始化。性能上会有些延迟。 */ public class SingletonLH { private static SingletonLH instance; private SingletonLH(){} public static synchronized SingletonLH getInstance() { if (instance == null) { instance = new SingletonLH(); } return instance; } }
静态内部类完成。
1 package com.iot.api.design.singleton; 2 3 /** 4 * @ProjectName: smartdata 5 * @Package: com.iot.api.design.singleton 6 * @ClassName: Singleton 7 * @Author: heluwei 8 * @Description: 静态内部类完成 单例模式 9 * @Date: 2020/1/16 17:49 10 * @Version: 1.0 11 */ 12 public class Singleton { 13 //1:构造器 14 private Singleton(){} 15 //2:利用静态内部类去创建类。 16 private static class SingletonInstance{ 17 private static final Singleton INSTANCE = new Singleton(); 18 } 19 //3:别人调用 20 public static Singleton getInstance(){ 21 return SingletonInstance.INSTANCE; 22 } 23 }
优缺点说明:
1):采用了类装载的机制来保证初始化实例时只有一个线程。
2):静态内部类方式在被装载时并不会立即实例化,而是在需要实例化时,调用getInstance() ,才会去装载SingletonInstance类。从而完成Singleton的实例化。
3):类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
4):优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。推荐使用。
应用实例: 1、一个党只能有一个主席。 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。 2、避免对资源的多重占用(比如写文件操作)。
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
使用场景: 1、要求生产唯一序列号。 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
需要频繁的进行创建和销毁的对象,创建对象时耗时过多或耗费资源过多(就是重量级对象),但又经常用到的对象,工具类对象,频繁访问数据库或文件的对象(数据源,session工厂等)。