概述
Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。
意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
例子
1.ASP.NET某应用程序对应的Application必须是唯一的。
2.不管在什么时候谈到地球,它都是指同一个地球。
3.某全局计数器对象是必须是唯一的,否则会使计数失败。
UML类图

代码:对应UML类图
1
/// <summary>
2
/// UML类图对应单件类
3
/// </summary>
4
public class Singleton
5
{
6
private static Singleton instance;
7
8
private Singleton() { }
9
10
public static Singleton Instance
11
{
12
get
13
{
14
if (instance == null)
15
{
16
instance = new Singleton();
17
}
18
return instance;
19
}
20
}
21
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

1
/// <summary>
2
/// UML类图对应客户端程序类
3
/// </summary>
4
public class MainApp
5
{
6
public static void Main()
7
{
8
Singleton s1 = Singleton.Instance;
9
Singleton s2 = Singleton.Instance;
10
11
if (s1 == s2)
12
{
13
Console.WriteLine("Object are the same instance");
14
}
15
16
Console.Read();
17
}
18
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

代码:六种实现方式
1.最简单的实现,但不支持线程安全
1
/// <summary>
2
/// 最简单的单件模式
3
/// 不支持多线程安全
4
/// </summary>
5
public class Singleton1
6
{
7
private Singleton1() { }
8
9
private Singleton1 instance = null;
10
11
public Singleton1 Instance
12
{
13
get
14
{
15
if (this.instance == null)
16
{
17
this.instance = new Singleton1();
18
}
19
return this.instance;
20
}
21
}
22
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

2.支持线程安全,但是不支持多线程的并发操作
1
/// <summary>
2
/// 线程安全
3
/// 但不支持线程并发
4
/// </summary>
5
public class Singleton2
6
{
7
private Singleton2() { }
8
9
private Singleton2 instance = null;
10
11
private static object objLock = new object();
12
13
public Singleton2 Instance
14
{
15
get
16
{
17
lock (objLock)
18
{
19
if (this.instance == null)
20
{
21
this.instance = new Singleton2();
22
}
23
}
24
return this.instance;
25
}
26
}
27
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

3.支持线程安全,使用双检查(Double Check),支持多线程的并发操作
1
/// <summary>
2
/// 线程安全
3
/// 支持线程并发
4
/// </summary>
5
public class Singleton3
6
{
7
private Singleton3 instance = null;
8
9
private Singleton3() { }
10
11
private static object objLock = null;
12
13
public Singleton3 Instance
14
{
15
get
16
{
17
if (this.instance == null)
18
{
19
lock (objLock)
20
{
21
if (this.instance == null)
22
{
23
this.instance = new Singleton3();
24
}
25
}
26
}
27
return this.instance;
28
}
29
}
30
31
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

4.使用静态初始化方式,但不支持缓实例化
1
/// <summary>
2
/// 静态初始化
3
/// 但不实现缓初始化
4
/// </summary>
5
public class Singleton4
6
{
7
private Singleton4() { }
8
9
private readonly static Singleton4 Instance = new Singleton4();
10
}

2

3

4

5

6

7

8

9

10

5.使用静态初始化方式,且支持缓实例化,但引入了附加类
1
/// <summary>
2
/// 静态初始化
3
/// 实现缓初始化
4
/// </summary>
5
public class Singleton5
6
{
7
private Singleton5() { }
8
9
public static Singleton5 Instance
10
{
11
get
12
{
13
return Nested.instance;
14
}
15
}
16
17
class Nested
18
{
19
private Nested() { }
20
21
internal readonly static Singleton5 instance = new Singleton5();
22
}
23
}
24

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

6.使用静态初始化方式,且支持缓实例化,实际使用时首选
1
/// <summary>
2
/// 静态实例
3
/// 实现缓初始化
4
/// .NET下的首选方式
5
/// </summary>
6
public class Singleton6
7
{
8
private static Singleton6 instance;
9
10
private Singleton6() { }
11
12
public static Singleton6 Instance
13
{
14
get
15
{
16
if (Singleton6.instance == null)
17
{
18
Singleton6.instance = new Singleton6();
19
}
20
return instance;
21
}
22
}
23
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

代码:完整例子
实现简单计数功能
1
/// <summary>
2
/// 计数器类
3
/// </summary>
4
public class SingletonCounter
5
{
6
/// <summary>
7
/// 将构造函数置为私有
8
/// </summary>
9
private SingletonCounter() { }
10
11
private static SingletonCounter instance;
12
13
public static SingletonCounter Instance
14
{
15
get
16
{
17
// 缓实例化
18
if (instance == null)
19
{
20
instance = new SingletonCounter();
21
}
22
return instance;
23
}
24
}
25
26
// 存放计数结构
27
private int num = 0;
28
29
// 计数
30
public void Add()
31
{
32
this.num++;
33
}
34
35
// 获取计数结果
36
public int GetNum()
37
{
38
return this.num;
39
}
40
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

1
/// <summary>
2
/// 执行计数类
3
/// </summary>
4
public class DoCounter
5
{
6
public void Counter()
7
{
8
SingletonCounter sc;
9
10
for (int i = 0; i < 10; i++)
11
{
12
// 每次使用到计数器对象都重新赋值
13
sc = SingletonCounter.Instance;
14
sc.Add();
15
Console.WriteLine(sc.GetNum());
16
}
17
}
18
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

1
/// <summary>
2
/// 客户端
3
/// </summary>
4
public class MyApp
5
{
6
public static void Main()
7
{
8
DoCounter dc = new DoCounter();
9
dc.Counter();
10
11
Console.Read();
12
}
13
}

2

3

4

5

6

7

8

9

10

11

12

13

总结
单件模式提供非常好的机制保证,实例唯一且有全局唯一访问点。
源代码:[下载]
参考
1. 【dofactory】ttp://www.dofactory.com/Patterns/Patterns.aspx#list
2. 【Terrylee】http://www.cnblogs.com/Terrylee/archive/2006/07/17/334911.html
3. 【卢振宇老师】http://zhenyulu.cnblogs.com/category/6930.html