单例模式解决什么问题
处理资源访问冲突
表示全局唯一. 在整个程序中,某些数据应该存储一份,这样的类,就应该设计成单例类。比如,SpringBoot应用的配置项。再比如 雪花算法的实现类。
实现单例
如何实现单例呢,或者说怎样能称得上单例呢?首先,单例要求全局唯一,那就是说不允许外部随随便便new一个新对象.
这句话里,至少有两个点:1.不允许外部new对象。 2.需要类内部new对象,并提供给外部进行使用。其实很简单的,单例类的构造方法需要是private权限的,提供一个public方法,用于外部获取本对象。
另外,我们写的程序都是运行在多线程环境的,所以我们还需要考虑线程安全的问题。还有,说过线程安全,自然而然,就会想到锁,想到锁,就要想到性能问题。
核心概念
保证某个类在一个运行环境中只有一个实例, 并提供一个访问该实例的全局节点。
单例的实现
懒汉式
测试代码
饿汉式
测试代码
双重检查锁
测试代码
问题
1、单例模式同时解决了两个问题,所以单例模式违反了单一职责原则:
1、保证一个类只有一个实例.
2、为该实例提供了一个全局访问节点.2、单例模式可能会掩盖不良设计,比如程序各组件之间项目了解过多。3、该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。4、单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象。由于单例类的构造函数是私有的, 而且绝大部分语言无法重写静态方法, 所以你需要想出仔细考虑模拟单例的方法。要么干脆不编写测试代码, 或者不使用单例模式。
与其他模式的关系
外观模式类通常可以转换为单例模式类, 因为在大部分情况下一个外观对象就足够了。
如果你能将对象的所有共享状态简化为一个享元对象, 那么享元模式就和单例类似了。但这两个模式有两个根本性的不同。
只会有一个单例实体, 但是享元类可以有多个实体, 各实体的内在状态也可以不同。
单例对象可以是可变的。享元对象是不可变的。
抽象工厂模式、 生成器模式和原型模式都可以用单例来实现。
最后
希望和你一起遇见更好的自己
领取专属 10元无门槛券
私享最新 技术干货