概述
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 /// 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 }
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 /// 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 }
代码:六种实现方式
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 /// </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.支持线程安全,但是不支持多线程的并发操作
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 /// </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 }
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 /// </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 }
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 /// </summary>
5 public class Singleton4
6 {
7 private Singleton4() { }
8
9 private readonly static Singleton4 Instance = new Singleton4();
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 /// </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
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 /// .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 }
代码:完整例子
实现简单计数功能
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 /// </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 }
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 /// </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 }
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 /// </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 }
总结
单件模式提供非常好的机制保证,实例唯一且有全局唯一访问点。
源代码:[下载]
参考
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