创建型模式的主要特点是:将对象的创建与使用分离。以此降低系统的耦合度
在很多系统设计中要求某些类的实例全局只能有一份,以此保证数据一致性,这就是所谓的单例模式。
单例模式的定义为:一个类只能有一个实例,且该类能够自行创建出这个实例并向外部提供的模式。
优点:
- 内存中只存储一份实例,减少了内存开销
- 避免资源的多重占用
- 单例类有全局唯一的访问入口,严格控制外部的访问
缺点:
- 单例模式一般没有接口,扩展困难
应用场景
- 需要频繁创建或者销毁的类,可以降低内存压力,减少GC
- 创建实例时占用资源过多,或者耗时较长,且经常使用
设计重点
- 私有化构造器
- 线程安全
- 双重检查
- 延迟加载
- 序列化和反序列化安全
- 反射
懒汉式单例
存在问题:每次访问都需要进行同步,耗费性能
public class LazySingleton {// volatile 只保证可见性和有序性,不保证原子性private static volatile LazySingleton instance = null;// 私有化构造器private LazySingleton(){}// 通过加锁的方式避免了重复创建实例public static synchronized LazySingleton getInstance() {if (instance == null){/*** 步骤:* 1. 分配对象空间* 2. 初始化对象* 3. instance指向被分配好的内存地址** 步骤2,3是可以发生交换的,这也是指令重排序问题,而volatile则很好的解决了这一问题*/instance = new LazySingleton();}return instance;}}
双重检查
优点:仅在第一次获取实例的时候进行同步
public class LazySingleton {// 这里不再需要volatile去保证有序性了,因为下面的双重检查可以确保实例只会有一份private static LazySingleton instance = null;// 私有化构造器private LazySingleton(){}// 双重检查public static LazySingleton getInstance() {if (instance == null){synchronized (LazySingleton.class){if (instance == null){instance = new LazySingleton();}}}return instance;}}
静态内部类
优点:初始化Singleton类的时候并不会初始化 INSTANCE ,只有首次调用的时候才会进行初始化,这样即保证了线程安全,也可以保证Singleton实例的唯一
class Singleton{// 静态内部类private static class InnerClass{private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return InnerClass.INSTANCE;}}
枚举
推荐使用的一种方式,因为基于枚举的特点,它无法在任何时候被修改,如果测试就可以发现其他方式都可以被反射修改实例,但是枚举是无法被修改的。
enum Singleton{INSTANCE;}
饿汉式单例
特点:在类加载的时候就已经创建好了对象,直接调用接口,先天避免了线程安全问题
class HungrySingleton{private static final HungrySingleton instance = new HungrySingleton();// 构造器私有化private HungrySingleton(){}public static HungrySingleton getInstance() {return instance;}}
