实现Singleton模式
常见的设计模式有许多,不过在面试过程中要应聘者完整的实现一个非Singleton莫属,但如何写好Singleton还是有许多要注意的地方的。
简单的单线程解法:
public sealed class Singleton1 { private Singleton1() { } private static Singleton1 instance = null; public static Singleton1 Instance { get { if (instance == null) instance = new Singleton1(); return instance; } } }
适应多线程但效率不高的解法:这样每次访问都要加锁,这是非常耗时的。
public sealed class Singleton2 { private Singleton2() { } private static readonly object syncObj = new object(); private static Singleton2 instance = null; public static Singleton2 Instance { get { lock (syncObj) { if (instance == null) instance = new Singleton2(); } return instance; } } }
避免不必要的加锁操作:只有在没实例化时加锁判断,否则直接返回实例
public sealed class Singleton3 { private Singleton3() { } private static object syncObj = new object(); private static Singleton3 instance = null; public static Singleton3 Instance { get { if (instance == null) { lock (syncObj) { if (instance == null) instance = new Singleton3(); } } return instance; } } }
C#特性的解法:利用静态构造函数,不过有个缺点是不是第一次调用属性Instance时创建实例,而是第一次用到Singleton4时就会被创建,例如调用静态方法Print时就会创建,这样会过早创建实例,从而降低内存使用率。
(对于较小的对象,可以忽略这点)
public sealed class Singleton4 { private Singleton4() { } public static void Print() { Console.WriteLine("Singleton4 Print"); } private static Singleton4 instance = new Singleton4(); public static Singleton4 Instance { get { return instance; } } }
按需创建实例:避免了Singleton4的过早创建问题,通俗的讲就是再套多一层,利用嵌套类的静态构造函数来构造这个实例,而这个嵌套类是不包含任何方法的且是私有的,所以就避免了调用Singleton的静态方法就把实例提前创建了的问题。
public sealed class Singleton5 { Singleton5() { } public static void Print() { Console.WriteLine("Singleton5 Print"); } public static Singleton5 Instance { get { return Nested.instance; } } class Nested { static Nested() { } internal static readonly Singleton5 instance = new Singleton5(); } }
补充说明:在C++下实现Singleton就麻烦得多了,实现垃圾回收需要用到auto_ptr,解决线程安全的问题需要使用到第三方的线程库(或者自己写),例如boost库。