xml地图|网站地图|网站标签 [设为首页] [加入收藏]
设计模式,objects遇到的小坑
分类:编程

AlbumView控件

今天我们来探索一下Singleton设计模式的实现及应用场景。

1、C#中LINQ to Objects中延迟查询的陷阱(其他类型的LINQ也基本一致)

一、          样式一

Singleton模式属于Creational Type(创建型)设计模式的一种。该模式一般用于确保在应用中仅创建一个某类的instance,在应用中的各个地方对该类的实例对象的引用均指向同一instacne。

之前在不了解LINQ延迟查询的时候,我使用下面的这种方式,将where语句的结果直接as为List<T>对象,结果得到的temp为NULL,苦思不得其解;

图片 1 

Singleton模式的优势:它提供了对资源的concurrent(一致)访问,避免了创建多个实例对象,浪费内存空间。

List<person> lst = new List<person>(){
    new person(){id=1,name="cyong"},
    new person(){id=2,name="lshan"}
};
List<person> temp = lst.Where(m => m.id > 1) as List<person>;

我们要实现上图中的效果,需要如下的操作:

Singleton模式实现准则:

 

  1. 从工具栏上的“Smobiler Components”拖动一个AlbumView控件到窗体界面上

1、确保仅有一个类的实例对象

求解思路:

 图片 2

2、提供对唯一实例对象的全局访问,该规则又可细分为3条规则。

  一开始以为是LINQ语句的问题,但是在反复测试之后,发现 lst.Where(m => m.id > 1) 确实是语法正确的,并且能够在调用ToList()扩展方法后返回正确的结果集;

  1. 修改AlbumView的属性
    1. load事件代码
  • 声明该类的所有构造器为private
  • 提供返回实例对象的引用的静态方法
  • 实例对象被存储为类的private static字段

  而后,考虑是as的问题,查看as的使用方式,发现as是类型安全的转换方式,当转换失败时不会报错,而是返回null;但是查看文档发现Where语句返回的是IEnumerable<TSource>,而IEnumerable<T>在一般情况下(比如我先将一个List<T>转换为IEnumerable<T>,再通过一次as转换回来)是可以正常转换为List<T>的;

C#:

下面通过例子实现Singleton模式,在具体实现时,我们首先实现不使用Singleton模式的代码,然后一步一步地将其改造成Singleton模式。

求助:

private void TestAlbumView_Load(object sender, EventArgs e)

 1 namespace Singleton
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Singleton s1 = new Singleton();
 8             s1.PrintMessage("this is first message");
 9 
10             Singleton s2 = new Singleton();
11             s2.PrintMessage("this is second message");
12 
13             Console.ReadKey();
14         }
15     }
16     class Singleton
17     {
18         private static int counter = 0;
19         public Singleton()
20         {
21             counter++;
22             Console.WriteLine("这是第"+counter.ToString()+"次调用构造函数");
23         }
24         public void PrintMessage(String str)
25         {
26             Console.WriteLine(str);
27         }
28     }
29 }

  然后就将这个问题抛给了群里面的一群大神。经过一番指点,才发现这个问题的缘由是LINQ的懒加载(延迟查询)。

        {

运行结果如下图:

  上文档:

            DataTable matTable = new DataTable();

图片 3

  LINQ查询简介

            matTable.Columns.Add("MAT_DESC1", typeof(string));

 

  文档中介绍到【查询变量本身只存储查询命令。查询的实际执行将推迟到“foreach”语句中循环访问查询变量之后进行;同时,也可以通过ToList或者ToArray方法强制立即执行,以将查询结果缓存到单个集合对象中】

 

  可以看出,在不使用Singleton模式时,每次使用类Singleton的PrintMessage方法时,都需要创建一个新的实例对象,这造成了极大的浪费。下面我们按照上面所说的准则将它改造成使用Singleton模式。

  Enumerable.Where<TSource>方法(IEnumerable<TSource>,Func<TSource,Int32,Boolean>).aspx)

            matTable.Rows.Add();

 1 namespace Singleton
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Singleton s1 = Singleton.getInstance;
 8             s1.PrintMessage("this is first message");
 9 
10             Singleton s2 = Singleton.getInstance;
11             s2.PrintMessage("this is second message");
12 
13             Console.ReadKey();
14         }
15     }
16     public sealed class Singleton
17     {
18         private static int counter = 0;
19         private static Singleton instance=null;
20 
21         public static Singleton getInstance
22         {
23             get
24             {
25                 if (instance == null)
26                     instance = new Singleton();
27                 return instance;
28             }
29         }
30         private Singleton()
31         {
32             counter++;
33             Console.WriteLine("这是第"+counter.ToString()+"次调用构造函数");
34         }
35         public void PrintMessage(String str)
36         {
37             Console.WriteLine(str);
38         }
39     }
40 }

  此方法使用的是LINQ的延迟查询。

            matTable.Rows[0]["MAT_DESC1"] = "q1";

运行结果如下图:

结论:

            matTable.Rows.Add();

图片 4 

  1、LINQ查询只是缓存查询命令,要访问查询结果,应该使用foreach去迭代或者使用ToList()或者ToArray方法强制立即执行并缓存到集合对象中。

            matTable.Rows[1]["MAT_DESC1"] = "q2";

  另外,需要注意的是,不要忘了在Singleton类的声明中添加sealed关键字,它确保了Singleton类不可被继承。当Singleton类可被继承且继承类位于Singleton基类外部时,由于Singleton基类的构造函数声明为private,此时运行程序会产生Singleton.Singleton()受保护级别限制不可访问的编译错误;当Singleton类可被继承且继承类位于Singleton基类内部构成嵌套类时,这时在main()方法中就可以创建多个继承类的instance,这就违背了Singleton模式的设计初衷:仅能创建该类型的一个instance。

  2、MSDN文档不得不看看。

            matTable.Rows.Add();

  最后,上述代码仅在单线程环境中运行良好,在下篇中介绍多线程环境中的实现,及Double-checked locking和lazy initialization的相关概念。

附图:

            matTable.Rows[2]["MAT_DESC1"] = "q3";

  1、同行指教

            matTable.Rows.Add();

图片 5

            matTable.Rows[3]["MAT_DESC1"] = "q4";

图片 6

            matTable.Rows.Add();

 

本文由澳门新葡亰手机版发布于编程,转载请注明出处:设计模式,objects遇到的小坑

上一篇:没有了 下一篇:自学课程,创建工作集并将element加入工作集中
猜你喜欢
热门排行
精彩图文