上面一篇主要阐述了这个项目的实现目的和架构设计.下面开始是对其中的类的分析:

首先分析的是ImportManager,可以看到客户端的代码访问的就是这个类.

我在ImportManager类中使用了外观模式,对客户端代码屏蔽了具体操作的代码.

这个类是一个singleton,具体的实现主要有下面这段代码:

 1         /// <devdoc>
 2         /// The singleton instance to use with static methods.
 3         /// </devdoc>
 4         // see this post (http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx) on why we do this
 5         internal static ImportManager Current
 6         {
 7             get
 8             {
 9                 if (instance == null)
10                 {
11                     lock (syncObject)
12                     {
13                         if (instance == null)
14                         {
15                             instance = new ImportManager();
16                         }
17                     }
18                 }
19                 return instance;
20             }
21         }

相信,读过设计模式的朋友对上面这段代码都很熟悉吧.

Singleton 式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程 序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。

从另一个角度来说,Singleton模式其实也是一种职责型模式。因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责!

这种方式的 实现对于线程来说是安全的。我们首先创建了一个进程辅助对象,线程在进入时先对辅助对象加锁然后再检测对象是否被创建,这样可以确保只有一个实例被创建, 因为在同一个时刻加了锁的那部分程序只有一个线程可以进入。这种情况下,对象实例由最先进入的那个线程创建,后来的线程在进入时(instence == null)为假,不会再去创建对象实例了。但是这种实现方式增加了额外的开销,损失了性能。

我在开发过程中还遇到一个问题.

在客户端如下使用ImportManager:

1                 if (ofd.ShowDialog ()==DialogResult.OK )
2                 {
3                     ImportManager.EndReport +=new EndReportEventHandler(worker_EndWork );
4                     ExecuteDelegate ed = new ExecuteDelegate( ExcelImportDB );
5                     ed.BeginInvoke(ofd.FileName,null,null);                    
6                 }

第一次使用一切正常,而第二次,第三次会发现对话框会弹出来多次的情况,而且第二次就会弹出来二次,第三次选择文件时会弹出来三次.

后来在调试过程中,发现是事件引起的.在到网上查了事件的文章,才知道原来事件在结束后,需要把它释放.以前由于使用的不是静态类,所以不会发生这种事情.但是这次使用了singleton模式,事件始终在内存中没有被释放,所以加了以下语句就解决了:

ImportManager.EndReport -=new EndReportEventHandler(worker_EndWork );

在结束后调用这句话,就不会出现上面这个问题了.
后面是源代码:
 1     public sealed class ImportManager
 2     {
 3         private static volatile ImportManager instance;
 4         private TranContext currentContext;
 5         private static object syncObject = new object();
 6         public static event EndReportEventHandler EndReport;
 7         private ImportManager()
 8         {
 9         }
10         /// <devdoc>
11         /// The singleton instance to use with static methods.
12         /// </devdoc>
13         // see this post (http://blogs.msdn.com/brada/archive/2004/05/12/130935.aspx) on why we do this
14         internal static ImportManager Current
15         {
16             get
17             {
18                 if (instance == null)
19                 {
20                     lock (syncObject)
21                     {
22                         if (instance == null)
23                         {
24                             instance = new ImportManager();
25                         }
26                     }
27                 }
28                 return instance;
29             }
30         }
31         public static void ExcelImportDB(string key,string askFileName,string operation)
32         {
50             ArgumentValidation.CheckForEmptyString (key,"key");
51             ArgumentValidation.CheckForEmptyString (askFileName,"askFileName");
52             ArgumentValidation.CheckForEmptyString (operation,"operation");
53             CreateContext(key,askFileName,operation);            
54             Current.currentContext.Execute();
55         }
56         private TranContext createContext(string key,string askFileName,string operation)
57         {
58             return new TranContext (key,askFileName,operation);
59         }
60         private static void CreateContext(string key,string askFileName,string operation)
61         {
62             if (Current.currentContext ==null)
63             {
64                 Current.currentContext=new TranContext (key,askFileName,operation);
65                 Current.currentContext.EndReport +=new EndReportEventHandler(Current.OnEndReport);
66             }
67         }
68         private void OnEndReport(object sender,EndReportEventArgs e )
69         {
70             if (EndReport != null)
71             {
72                 EndReport(this, e);
73             }
74         }
75     }

posted on 2007-05-15 09:44  nerozhang  阅读(1497)  评论(3编辑  收藏  举报