设计模式一--单例模式

单例模式

允许一个类只能有一个实例为系统提供服务,并且实例必须通过new关键字获取

为什么要使用单例模式(单例模式的优点)

1:内存中只有一个实例,则可以减少很多内存开支
2:当一个类的创建需要更多的资源的时候,单例模式就能够减少对系统的性能开销,启动时创建并且永久化对象
3:单例模式可以避免对文件或者资源的多重占用
4:单例模式可以设置在系统的全局访问点,优化和共享资源访问

单例模式下的两种创建方式

饿汉式

饿汉式,就是在系统启动的时候就进行实例化,并不关心什么时候才会使用

public class Singlton{
  //static实例
  private static Singlton singlton = new Singlton();
  //构造方法
  private Singlton(){
  }
  //获取方法
  public static Singlton getInstance(){
    return singlton;
  }
}

懒汉式

懒汉式,在需要的时候才进行实例化,减少启动所使用的时间


public class Singlton{
    //对象并不会启动的时候实例化
    private static Singlton singlton = null;
    //构造方法
    private Singlton(){
    };

    public static Singlton getInstance(){
        //判断是否初始化过,可以避免空指针,或者重复初始化,减少开销
        if(singlton == null){
            //加锁,再次判断,是防止高并发的时候重复初始化对象
            synchronized(){
                if(singlton == null){
                    singlton = new Singlton();
                }
            }
        }
        return singlton;
    }
}

单例模式的缺点

1:单例模式下没有接口,扩展比较困难,想要扩展必须修改代码
2:单例模式下测试困难,并行开发环境下单例模式必须先完成才能进行测试
3:单例模式和单一职责原则有冲突(一个类应该只实现一个逻辑,而不关心是否单例)

单例模式常见场景

1:要求生成唯一系列号
2:项目中需要共享访问点或者共享数据
3:创建对象需要消耗更多的资源的时候,比如IO和数据库连接
4:大量定义常量方法的时候,比如工具类等

Spring中单利模式的应用(双重判断加锁的单利模式)

//三级缓存

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);



/**
 * 获取Bean的方式, 从AbstractBeanFactory.getBean(String name)--> 
 *     AbstractBeanFactory. doGetBean(String beanName  final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) --> getSingleton(String beanName)
 */
public Object getSingleton(String beanName){
    //参数true设置标识允许早期依赖
    return getSingleton(beanName,true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //检查缓存中是否存在实例
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        //如果为空,则锁定全局变量并进行处理。
        synchronized (this.singletonObjects) {
            //如果此bean正在加载,则不处理
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {  
                //当某些方法需要提前初始化的时候则会调用addSingleFactory 方法将对应的ObjectFactory初始化策略存储在singletonFactories
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //调用预先设定的getObject方法
                    singletonObject = singletonFactory.getObject();
                    //记录在缓存中,earlysingletonObjects和singletonFactories互斥
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

参考资料:设计模式之禅(二)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容