设计模式C#实现(六)——单例模式

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

 

构成:

1.私有的构造函数

2.私有静态的实例

3.返回实例的静态方法

  public class Singleton
    {
        private static Singleton uniqueInstance = new Singleton();
        private Singleton() { Console.WriteLine("this is a new singleton"); }
        public static Singleton getInstance()
        {
            if (uniqueInstance == null)
            {
                return uniqueInstance;
            }
            return uniqueInstance;
        }
    }

 

这种叫做饿汉模式,实例在类加载时就创建了,缺点是如果实例如果消耗大量的资源而没有使用就会造成浪费,另一种懒汉模式,实例在被使用时才创建,

  public class Singleton
    {
        private static Singleton uniqueInstance;
        private Singleton() { Console.WriteLine("this is a new singleton"); }
        public static Singleton getInstance()
        {
            if (uniqueInstance == null)
            {
                return uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
    }

但是这不是线程安全的

例如

class Program {
     
        static void Main(string[] args) {
            while (true) {
                Thread t1 = new Thread(Test);
                t1.Start();
            }
        }
        static void Test() {
            Singleton s = Singleton.getInstance();
        }
       
    }

执行的结果有可能是这样

程序创建了多个实例,这不是我们想要的结果,原因是某个线程if (uniqueInstance == null)语句执行后让出了使用权,当它重新获得CPU使用权的时候,可能别的CPU已经创建了实例,而它并不知道,继续执行return uniqueInstance= new Singleton();导致出现多个实例。

因此,要为方法加锁

  public class Singleton
    {
        private static Singleton uniqueInstance;
        private Singleton() { Console.WriteLine("this is a new singleton"); }
        private static readonly object syncRoot = new object();
        public static Singleton getInstance()
        {
            lock (syncRoot)
            {
                if (uniqueInstance == null)
                {
                      return uniqueInstance = new Singleton();
                }
            }

            return uniqueInstance;
        }
    }

但是这又带来了一个问题,在实例已经创建完成了,但还是会有大量的线程卡在lock (syncRoot),它们都还会尝试创建实例,这降低了性能

为此,还要为此方法创建另外一个验证

 public static Singleton getInstance()
        {
            if (uniqueInstance == null)
            {
                lock (syncRoot)
                {
                    if (uniqueInstance == null)
                    {
                       return uniqueInstance = new Singleton();
                    }
                }
            }
            return uniqueInstance;
        }

此时,当实例已经创建完成之后,各线程不再访问临界区,提高了性能

 

单例模式和静态类的比较

1.单例模式可以懒加载,静态类执行更快(为什么?),即在不同条件下二者有不同的性能表现

2.单例可以继承和override

3.单例易于模拟,利于测试

4.单例利于维护状态信息

 

update:

1.静态类执行更快?

因为静态类在编译时绑定(什么是编译时绑定?)

2.stackoverflow上的回答

Vadluri Sreenu

  1. Singleton object stores in Heap but, static object stores in stack
  2. We can clone the object of Singleton but, we can not clone the static class object
  3. Singleton class follow the OOP(object oriented principles) but not static class
  4. we can implement interface with Singleton class but not with Static class.

Jon Skeet

A singleton allows access to a single created instance - that instance (or rather, a reference to that instance) can be passed as a parameter to other methods, and treated as a normal object.

A static class allows only static methods.

 

posted @ 2015-09-17 09:35  妖刀Dreamcast  阅读(256)  评论(0编辑  收藏  举报