定义:
作为对象的创建模式[GOF95], Singleton模式确保其一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单态类。
单态类有以下几个特点:
- 单态类只能有一个实例。
- 单态类必须自己创建自己的这个实例。
- 单态类必须给所有其他对象提供这个实例。
以下是单态模式的几个实现方法:
1 无线程安全。
1 public sealed class Singleton
2 {
3 static Singleton instance=null;
4
5 Singleton()
6 {
7 }
8
9 public static Singleton Instance
10 {
11 get
12 {
13 if (instance==null)
14 {
15 instance = new Singleton();
16 }
17 return instance;
18 }
19 }
20 }
21
2 {
3 static Singleton instance=null;
4
5 Singleton()
6 {
7 }
8
9 public static Singleton Instance
10 {
11 get
12 {
13 if (instance==null)
14 {
15 instance = new Singleton();
16 }
17 return instance;
18 }
19 }
20 }
21
上面这个写法是没有线程安全,当有两个线程同时走到if (instance==null),并发现都是True,那将会创建两个实例。所以不推荐使用这个方法。
2 简单线程安全
1 public sealed class Singleton
2 {
3 static Singleton instance=null;
4 static readonly object padlock = new object();
5
6 Singleton()
7 {
8 }
9
10 public static Singleton Instance
11 {
12 get
13 {
14 lock (padlock)
15 {
16 if (instance==null)
17 {
18 instance = new Singleton();
19 }
20 return instance;
21 }
22 }
23 }
24 }
2 {
3 static Singleton instance=null;
4 static readonly object padlock = new object();
5
6 Singleton()
7 {
8 }
9
10 public static Singleton Instance
11 {
12 get
13 {
14 lock (padlock)
15 {
16 if (instance==null)
17 {
18 instance = new Singleton();
19 }
20 return instance;
21 }
22 }
23 }
24 }
上面这个写法加了lock (padlock)语句,那就能保证只有一个线程进入并创建唯一的一个实例。但是这个方法有一点不足,就是每次Return之前都要加锁解锁,影响了性能。
3.两次检查
1public sealed class Singleton
2{
3 static Singleton instance=null;
4 static readonly object padlock = new object();
5
6 Singleton()
7 {
8 }
9
10 public static Singleton Instance
11 {
12 get
13 {
14 if (instance==null)
15 {
16 lock (padlock)
17 {
18 if (instance==null)
19 {
20 instance = new Singleton();
21 }
22 }
23 }
24 return instance;
25 }
26 }
27}
28
2{
3 static Singleton instance=null;
4 static readonly object padlock = new object();
5
6 Singleton()
7 {
8 }
9
10 public static Singleton Instance
11 {
12 get
13 {
14 if (instance==null)
15 {
16 lock (padlock)
17 {
18 if (instance==null)
19 {
20 instance = new Singleton();
21 }
22 }
23 }
24 return instance;
25 }
26 }
27}
28
这个方法在加锁之前先判断instance 是否为空,这样只有为Null的时候才加锁并创建一个新的实例,这样就能避免了“简单线程安全”写法的性能问题。
4.
1public sealed class Singleton
2{
3 static readonly Singleton instance=new Singleton();
4
5 // Explicit static constructor to tell C# compiler
6 // not to mark type as beforefieldinit
7 static Singleton()
8 {
9 }
10
11 Singleton()
12 {
13 }
14
15 public static Singleton Instance
16 {
17 get
18 {
19 return instance;
20 }
21 }
22}
2{
3 static readonly Singleton instance=new Singleton();
4
5 // Explicit static constructor to tell C# compiler
6 // not to mark type as beforefieldinit
7 static Singleton()
8 {
9 }
10
11 Singleton()
12 {
13 }
14
15 public static Singleton Instance
16 {
17 get
18 {
19 return instance;
20 }
21 }
22}
5.
1
2 public sealed class Singleton
3 {
4 Singleton()
5 {
6
7 }
8 public static Singleton Instance
9 {
10 get
11 {
12 return Nested.instance;
13 }
14 }
15
16 class Nested
17 {
18 static Nested()
19 {
20
21 }
22
23 internal static readonly Singleton instance = new Singleton();
24 }
25 }
2 public sealed class Singleton
3 {
4 Singleton()
5 {
6
7 }
8 public static Singleton Instance
9 {
10 get
11 {
12 return Nested.instance;
13 }
14 }
15
16 class Nested
17 {
18 static Nested()
19 {
20
21 }
22
23 internal static readonly Singleton instance = new Singleton();
24 }
25 }