《单例模式》你需要注意的问题

 

单例模式大家都很熟悉,但是使用过程中,稍微不注意就会出现大问题。

 

单例模式:该类在整个系统生命周期中有且只有一个实例。

 

 

 

单例的创建:

注意问题:

  1. 构造函数 私有化 :保证 实例化该类通过统一的接口
  2. 提供一个统一的接口获取类的实例
  3. 保证线程同步

 例如:

public class CommonQuery
{

        
private CommonQuery() { }

        
object aLocker = new object();
        
static readonly CommonQuery _cmQuery = null;

        
public static CommonQuery GetCommonQuery()
        {
          if(_cmQuery!=null)
           {return _cmQuery;}
      lock(aLocker)
      {
        if(_cmQuery==null)
        {
          _cmQuery = new CommonQuery();
        }
      
      }
      return _cmQuery;
        }
}

 

 

单例中应该避免的问题:

  1. 避免无限递归调用
  2. 尽量少将数据或其他类的实例保存到该单例类中的全局变量中(如果有必要除外)

 

以上2点问题主要针对内存的问题,因为单例是在整个系统生命周期中都一直存在,如果有大量信息被单例保存,可想而知,我们的内存伤不起啊,

导致的结果就是 内存溢出!

 

场景:

多任务定时采集某网站数据

该需求 核心我一般这么设计:至少2个类

  1. CommonQuery:单例,负责 采集任务初始化、线程控制、具体采集任务调度、采集结果/错误等后续处理、通知前端UI
  2. WebWorker:非单例,负责具体采集任务,执行结果将反馈给CommonQuery


 核心序列图:

 

 

核心类图:

 

 

基本上核心 就是上面2个类,

执行流程是:在CommonQuery中的 Start()方法中,生成N个(根据多线程需要)webWorker对象,执行具体任务,当该任务执行完成或者出错以后,便通过事件EFinished或者EError来

通知CommonQuery,此时CommonQuery 根据实际情况来处理是继续新建任务来执行,还是判断整个任务结束,通知前台UI。(整个过程采用多线程异步)

 

 注意点:

  1. 在CommonQuery中 不需要保存任何webworker实例!应该在Start()方法里面去new WebWorker对象
  2. 在WebWorker的EFinished/EError事件处理中(在CommonQuery中处理),千万别调用新的一轮采集任务的开始!(此时造成无限递归!灰常危险!!)
  3. 检查CommonQuery,尽量减少将变量保存下来

这几点主要针对内存的建议,一般这种采集任务执行时间都较长,有时候需要连续几天不停的采集,此时如果设计的有问题,出现以上3中情况,呵呵,您的内存伤不起啊。。。

 

 

 

 

 

 C#技术交流: 64913828

 

 

 

 

 

posted @ 2011-08-26 15:40  -Enchant  阅读(1618)  评论(2编辑  收藏  举报