今天我们来探索一下Singleton设计模式的实现及应用场景。
Singleton模式属于Creational Type(创建型)设计模式的一种。该模式一般用于确保在应用中仅创建一个某类的instance,在应用中的各个地方对该类的实例对象的引用均指向同一instacne。
Singleton模式的优势:它提供了对资源的concurrent(一致)访问,避免了创建多个实例对象,浪费内存空间。
Singleton模式实现准则:
1、确保仅有一个类的实例对象
2、提供对唯一实例对象的全局访问,该规则又可细分为3条规则。
- 声明该类的所有构造器为private
- 提供返回实例对象的引用的静态方法
- 实例对象被存储为类的private static字段
下面通过例子实现Singleton模式,在具体实现时,我们首先实现不使用Singleton模式的代码,然后一步一步地将其改造成Singleton模式。
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 }
运行结果如下图:
可以看出,在不使用Singleton模式时,每次使用类Singleton的PrintMessage方法时,都需要创建一个新的实例对象,这造成了极大的浪费。下面我们按照上面所说的准则将它改造成使用Singleton模式。
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 }
运行结果如下图:
另外,需要注意的是,不要忘了在Singleton类的声明中添加sealed关键字,它确保了Singleton类不可被继承。当Singleton类可被继承且继承类位于Singleton基类外部时,由于Singleton基类的构造函数声明为private,此时运行程序会产生Singleton.Singleton()受保护级别限制不可访问的编译错误;当Singleton类可被继承且继承类位于Singleton基类内部构成嵌套类时,这时在main()方法中就可以创建多个继承类的instance,这就违背了Singleton模式的设计初衷:仅能创建该类型的一个instance。
最后,上述代码仅在单线程环境中运行良好,在下篇中介绍多线程环境中的实现,及Double-checked locking和lazy initialization的相关概念。