单例模式
-
定义:
确保某一个类只有一个实例,而且自动实例化并向整个系统提供这个实例。
-
使用场景:
对于一些特定的场景,必须使用单例模式,例如:唯一序列号生成、定义静态方法和常量、共享访问点或者共享数据的场合。
-
UML:
- Singleton:单例类,只能通过getInstance()方法获取唯一实例对象。
-
优点:
- 单例模式的类在创建和销毁时,减少了内存的开销,防止内存泄漏。
- 当一个对象需要比较多的资源时,如读取配置、产生其他依赖对象时,可以通过在应用启动时直接创建一个单例对象,用永久驻留内存的方法可以减少系统性能的开销。
- 避免了对资源的多重占用。
-
缺点:
- 单例模式一般没有接口,无法扩展。
- 单例模式责任过重,在一定程度上违背了单一职责原则。
- 不适用于变化的对象,如果同一类型的对象总是在不同的用例场景发生变化,单例就会引发数据的错误,不能保存彼此的状态。
-
样例:
- 饿汉模式
public class Singleton{ private static Singleton instance = new Singleton() ; //构造方法私有化 private Singleton(){ } //通过getInstance()方法去获取,在声明都西昂的时候就初始化了,浪费内存。 public static Singleton getInstance(){ return instance ; } }
- 懒汉模式
public class Singleton{ private static Singleton instance ; private Singleton(){ } //特点:使用时才实例化,线程安全,但是由于每次需要同步性能较低,不建议使用。 public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton() ; } return instance ; } }
- 双锁DCL实现
public class Singleton{ private static Singleton instance = null ; private Singleton(){ } //第一次使用才创建 //第一层判断主要是为了避免不必要的同步 //第二层判断是为了在null情况下创建实例 //特点:解决了资源消耗、多余的同步、线程安全问题 //但是在某些情况下会失效(JVM指令重排序/原子性问题),需要在第一行中为instance添加volatile关键字。 public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ if(instance == null){ instance = new Singleton() ; } } } return instance ; } }
- 静态内部类
public class Singleton{ private Singleton(){ } //第一次加载Singleton类时并不会初始化instance,只有在第一次调用Singleton的getInstance()方法才会导致instance被初始化。 private static class SingletonHolder{ private static final Singleton instance = new Singleton() ; } public static Singleton getInstance(){ return SingletonHolder.instance ; } }
- 枚举模式
//写法简单,线程安全 public enum Singleton{ INSTANCE ; public void doSomeThing(){ //代码 } }