这是我参与新手入门的第3篇文章。
定义
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
使用场景
确保某个类有且只有一个对象的场景,避免产生多个对象而导致不必要的资源消耗。或者当创建一个对象要访问IO,数据库等高资源时考虑使用单例只创建一次实例对象。
优点
- 在内存中只有一个实例,减少了内存的开销,尤其是频繁的常见和销毁实例。
- 可以避免对资源的过多使用,如上诉使用场景所述。
缺点
- 没有接口,不便扩展并且与单一原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
代码实现
懒汉式
最简单的实现方式,第二方法加锁避免在多线程情况下出现异常情况,但是影响效率。
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance(){
if(Objects.isNull(instance)){
instance = new Singleton();
}
return instance;
}
public static synchronized Singleton getInstances(){
if(Objects.isNull(instance)){
instance = new Singleton();
}
return instance;
}
}
复制代码
饿汉式
没有加锁,执行效率会提高,但是在类加载时就初始化,没有实现拉加载浪费内存。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
复制代码
双重锁
双重锁的方式是方法级锁的优化,减少部分获取实例的耗时,同事也满足了满加载。
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (Objects.isNull(singleton)) {
synchronized (Singleton.class) {
if (Objects.isNull(singleton)) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
复制代码
枚举式
最简单的实现方式,使用枚举。枚举和Java普通类是一样的,不仅能有字段,还可以有自己的方法,最重要是默认线程安全的,在任何情况下他都是一个单例。
public enum Singleton {
INSTANCE;
public void doSomething() {
}
}
复制代码
封装工具类
在androd framework源码中有应用,我们可以封装一层单例工厂,将所有需要用单例模式的实例封装在SingletonFactory,减少代码冗余,个人推荐这种用法
public abstract class SingletonUtils<T> {
private T instance;
public abstract T create();
public final T getInstance(){
if(Objects.isNull(instance)){
synchronized (this){
if(Objects.isNull(instance)) instance = create();
}
}
return instance;
}
}
复制代码
public class SingletonFactory {
public static A getA() {
return new Singleton<A>() {
@Override
protected A create() {
return new A();
}
}.getInstance();
}
public static B getB() {
return new Singleton<B>() {
@Override
protected B create() {
return new B();
}
}.getInstance();
}
public static SensorOrientation getC() {
return new Singleton<C>() {
@Override
protected C create() {
return new C();
}
}.get();
}
}
复制代码
学习参考自《重学Java设计模式.pdf》《Android源码设计模式解析与实战》
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END