且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-06-09 09:13:23

一、单例模式的概念:

单例,即单一实例;

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

系统上下文:即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(s){
                  if(s==null){
                      s=new Single();
                  }
              }

         }
         return s;
     }
}

分析:

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

注意,在锁内,实例可被重新初始化,所以对实例加锁无意义。


方式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