团部培训笔记-设计模式-《2013-11-19 单例模式》

按:本文为ATIP团内部培训笔记,主讲人: winters1224,记录人: hunterkathy,转载请注明出处;

一、单例模式的概念

单例,即单一实例;

单例模式,保证整个系统的上下文中只有一个类的实例;

系统上下文:即ClassLoader;

第三方定义上下文:SpringIOC

二、单例模式的作用

1、节约内存:内存中只保留一份和实例相关的资源

应用:如配置文件和缓存

2、控制多线程同步

任意多个线程,都只访问一个实例,天然的实现“写同步”

三、单例模式的实现

方式1

public class Single{
    public static Single s;

    private Single(){}

    public static Single getInstance(){
         if(s==null){
              s=new Single();
         }
         return s;
    }
}

分析

方式1只适合单线程,当多个线程读进来,同时判断s==null时,将导致创建多个实例。

方式2

public class Single{
    public static Single s;

    private Single(){}
    public static synchronized Single getInstance(){
         if(s==null){
              s=new Single();
         }
         return s;
    }
}

分析

方式2的方法中增加了同步管理,多个线程之间,实现后进入者等待机制,满足了同步需求;

但是该实现中对整个方法加了同步锁,无需同步实现的操作也被加锁,存在性能问题;

另外,synchronized对环境要求苛刻,在特殊情况下将失效,如多cpu的情况。

方式3

public class Single{
    public static Single s;

    private Single(){}
    public static Single getInstance(){
         if(s==null){
              synchronized(Single.class){
                  if(s==null){
                      s=new Single();
                  }
              }

         }
         return s;
     }
}

分析

该实现为双重锁,即在方法中对class加锁。

注意,在锁内,实例可被重新初始化,所以对实例s加锁无意义。必须对所在类或其它实例加锁

方式4

public class Single{
    public static final Single s=new Single();
    private Single(){}
}

分析

要保证两点:

  1. 构造方法私有化——封装构造方法的可见性;
  2. 实例是静态的: static (final);

方式5

public Enum Single{
    S;
    private Single(){}
}

分析

使用枚举来实现单例,避免多线程同步问题,以及绝对避免多次实例化问题;

四、注意点

在多线程环境下,要注意考虑同步问题:

  1. 如何实现
  2. 写单例

五、模式协作

  1. 配合工厂模式:提供实例
  2. 配合亨元模式:copy机制,复用一个提供的实例 如:数据库连接池的应用,菜单树的应用
  3. 配合MVC模式:如servlet

六、项目应用

public class PrecastMethodFactory {
    /**
     * 空白公式和公式法,这个公式可以用单例。
     * <p>
     * 2013年10月12日 团长 增加公式法的单例
     *
     * @author 團長
     * @since 2013-9-9
     */
    private static final PremethodModel METHOD_BLANK = new BlankFormulaMethodModel(),
      METHOD_FMLA = new FormulaMethodModle();
    ……
}

Spring IOC配置:

<bean id="BaseDBService"
 class="com.sinosig.evaluation.base.service.impl.DefaultBaseDBServiceImpl">
     <property name="dao" ref="BaseMybatisDao" />
     <property name="batchDao" ref="BaseMybatisDao" />
</bean>

注:未定义scope的,默认都是SpringIOC的单例(不是指ClassLoader的);

七、单例模式总结

  1. 保证上下文中只有一个单例
  2. 节约内存
  3. 实现方式要点:封装构造方法的可见性
  4. 注意事项:多线程操作
  5. 与其它模式协作:工厂模式,亨元模式,mvc模式等
  6. 项目应用:部分预测方法

本文出自 “ ATIP團戰術策劃部” 博客,请务必保留此出处 http://atip3.blog.51cto.com/6312771/1331073