一、定义
确保一个类有且仅有一个实例,且自行化实例,并向整个系统提供这个实例。
二、通用代码
public class singleClass{
private static final SingleClass single = new SingleClass();
private SingleClass(){
//构造函数
}
public static SingleClass getInstance(){
//对外提供实例
return single;
}
public static void doSomethings(){
//其他类
}
}
三、优点
- 减少内存开支,特别是当一个类需要频繁创建、销毁时
- 减少系统的性能开销
- 避免资源的多重占用
- 可以设置全局访问点,优化和共享资源访问
四、缺点
- 不可扩展(也可以说是违反了开闭原则)
- 例模式一般不为接口
- 单例模式要求自行实例化且提供单一实例,然而接口和抽象类不可能被实例化,因此接口和抽象类对单例模式来说,没有任何意义
- 对测试不利,主要是并行开发中,如果单例类未完成,其他方法无法进行测试
- 与单一职责原则冲突。
- 单一职责要求只能有一个原因引起类的变更,即一个类只实现一个逻辑
- 但是单例类则会将多个业务逻辑整合在一个类中
五、应用场景
- 生产唯一序列号
- 项目中需要一个共享访问点或共享数据
- 创建一个对象需要消耗的资源过多。如访问IO和数据库
- 定义大量的静态常量和静态方法(当然这个也可以采用static来操作)
六、注意事项
- 线程不安全。第一次调用才进行实例化,即初始化对象为null,getInstance()中设定初始对象为null,则创建对象,否则返回现有的对象(代码如下文)。但是在高并发中,很容易出现对象还在创建,新线程就过来,发现对象仍为null,则会继续创建新对象,则单例会被破坏。
为避免这种情况,可在getInstance()方法前加Synchronized关键字public class singleClass{ private static final SingleClass single = null; private SingleClass(){ //构造函数 } public static SingleClass getInstance(){ //对外提供实例 if(single == null){ single = new SingleClass(); } return single; } public static void doSomethings(){ //其他类 } } - 对象复制会跳过构造方法,导致产生多个对象。但是这种一般不需要管,一般单例类的也不会主动被复制
七、实现方式
该段内容来自一文搞懂设计模式—单例模式 掘金 (juejin.cn)代码和讲解太好了,我就不班门弄斧了,想看实现代码的直接去这篇文章看吧
| 实现方式 | 优点 | 缺点 |
|---|---|---|
| 饿汉式 | 线程安全;简单直接;性能高 | 不能懒加载,会占用一定资源 |
| 懒汉式 | 迟加载,避免不必要的资源消耗 | 线程不安全;需要判断和创建,性能会有所影响 |
| 双重校验锁 | 线程安全的懒汉式变种 | /未知 |
| 静态内部类 | 线程安全的懒汉式变种 | /未知 |
| 枚举式 | 线程安全;防止反射工具和序列化破坏;简介明了 | /未知 |
八、扩展
设计固定数量的对象。也被称作有上限的多例模式。即在实例化时,直接实例多个单例对象