设计模式之单例模式

单例模式:

核心思想:类只实例化一次,并且提供一个全局访问点。(只有那个全局访问点对外开放,其他内容封装起来)

图片解析:

优点:

1由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能

 

2直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。惰性实例化避免了在应用程序启动时实例化不必要的 singleton

 

代码:

第一版本:(在单线程里面使用(不考虑线程内安全问题))

主要分为三步:1、静态实例变量(用于接收实例成员)2、构造函数私有化(外部不能实例化,不能获得实例)3、全局访问点(任何用户都从这里访问)

 

 1     //sealed:私有类:太监类(不能被继承)
 2     public sealed class Singleton
 3     {
 4         //第一步:创建一个 静态 私有的变量(用于接收 对象的实例)
 5         private static Singleton instance;
 6 
 7         //第二步:构造函数私有化(不能实例化)
 8         private Singleton()
 9         {
10         }
11 13 
14         //第三步:单例函数的“全局入口点” 静态
15         public static Singleton Instance
16         {
17             get
18             {
19                 //(唯一实例):没有就进行创建,有的话就不创建
20                 if (instance == null)
21                 {
22                     instance = new Singleton();
23                 }
24                 return instance;
25             }
26         }
27     } 

 

 

 

第二版本:(解决线程内安全问题)

使用lock锁的机制,解决多线程问题。但是在性能上降低的

 

 1     //sealed:私有类:太监类(不能被继承)
 2     public sealed class Singleton
 3     {
 4         //第一步:创建一个 静态 私有的变量(用于接收 对象的实例)
 5         private static Singleton instance;
 6 
 7         //第二步:构造函数私有化(不能实例化)
 8         private Singleton()
 9         {
10         }
11 
12         //第一版本的单例设计模式
13 
14         //第三步:单例函数的“全局入口点” 静态
15         public static Singleton Instance
16         {
17             get
18             {
19                 //(唯一实例):没有就进行创建,有的话就不创建
20                 if (instance == null)
21                 {
22                     instance = new Singleton();
23                 }
24                 return instance;
25             }
26         }
27     } 

 

 

3.第三版本:双重锁定机制

优点:
1》多线程安全

2》(*重点*)线程不是每次都加锁(单线程不用加lock,性能提升了)

3》允许实例化延迟到第一次访问对象时发生(只有第一次才创建)

 

 1     public sealed class singleton
 2     {
 3         private static singleton instance = null;
 4         private static readonly object padlock = new object();//用于锁的使用
 5         private singleton()
 6         {
 7         }
 8 
 9         public static singleton instance
10         {
11             get
12             {
13                 //双重锁定 (点线程里面 就不使用 lock,在性能上做了优化)
14                 if (instance == null)
15                 {
16                     //将当前线程 锁住:造成 资源额外的开销,造成性能上的降低 (内部会进行 很多的处理)
17                     lock (padlock)
18                     {
19                         if (instance == null)
20                         {
21                             instance = new singleton();
22                         }
23                     }
24                 }
25                 return instance;
26             }
27         }
28     }

 

4.第四版本:静态初始化(饿汉模式)这就和.Net的框架挂钩,这是在.Net里面推荐的使用方式:代码简便并效率高

特点:

1、(*)“依赖”.Net Framwork 内部进行处理 变量的初始化。
2、对实例化的控制很少(大部分都是.Net内部实现的)

3、饿汉模式是“首先方法”

 

 1     public sealed class Singleton
 2     {
 3         //静态只读的属性
 4         private static readonly Singleton instance = null;
 5 
 6         //静态构造函数:只要是在内存里面加载这个类(不管是实例化,还是调用这个类的静态成员)都会执行这个静态构造函数,并且不会消失
 7         //保证了线程内唯一:因为只实例化一次
 8         static Singleton()
 9         {
10             instance = new Singleton();
11         }
12 
13         //私有构造函数:保证类不能被实例化
14         private Singleton()
15         {
16         }
17 
18         //全局入口点
19         public static Singleton Instance
20         {
21             get
22             {
23                 return instance;
24             }
25         }
26 
27     }

 

上面的有一种问题,就是如果我的类里面如果有一个 静态方法SayHi(),在调用这个方法的时候,我不想将这个对象进行实例化,但是因为是静态构造函数,所以只要调用和这个类有关的对象都会调用静态构造函数,就会初始化实例化。解决方法:将静态初始化放到嵌套类里面。这样就不存在静态构造函数了,因为已经将他的静态初始化作用转移到了嵌套类里了。

5、最终版本:单例模式之饿汉模式 最终版(延迟初始化)

 将初始化 的工作 交给了 嵌套类 Nested 的静态构造函数,所以  调用不想 初始化  对象 的 代码时 就不会执行

 

 1     public sealed class Singleton
 2     {
 3 
 4         //不再使用静态构造函数 (但是他的  线程内唯一的  功能必须要实现)
 5         //static Singleton()
 6         //{
 7 
 8         //}
 9 
10         private Singleton()
11         {
12 
13         }
14 
15         public static Singleton Instance
16         {
17             get
18             {
19                 return Nested.instance;
20             }
21         }
22 
23         //调用这个方法的时候我并不想 调用 那个静态构造函数,对 其对象进行实例化
24         public static void SayHi()
25         {
26             Console.WriteLine("Hello");
27         }
28 
29 
30         //解决上面的问题 使用静态类,通过这个静态 进行对 上面的那个类 进行 实例化
31 
32         private class Nested
33         {
34             //注意这里不能是  private;因为那样的话 在外层类 里面就不能访问到了
35             internal static readonly Singleton instance = null;
36 
37             //将 外层类的  静态构造函数的功能在 下面这个 静态构造函数实现了(线程内唯一)
38             static Nested()
39             {
40                 instance = new Singleton();
41             }
42         }
43     }

 

 

posted @ 2013-11-30 16:48  小小gogo  Views(650)  Comments(2Edit  收藏  举报