C#设计模式-单例模式

一、 单例(Singleton)模式

单例模式的特点:

  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其它对象提供这一实例。

二、 单例(Singleton)模式应用场景

  1. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~ 
  2. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
  3. 网站的计数器,一般也是采用单例模式实现,否则难以同步。
  4. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
  5. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
  6. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
  7. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
  8. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。
  9. HttpApplication 也是单位例的典型应用。熟悉ASP.NET(IIS)的整个请求生命周期的人应该知道HttpApplication也是单例模式,所有的HttpModule都共享一个HttpApplication实例.

三、 单例(Singleton)模式的六种写法

  1. 简单实现

using System;
using System.Collections.Generic;
using System.Text;

namespace Singleton
{
    public sealed class Singleton1
    {
        private static Singleton1 instance = null;
        private Singleton1() { }
        public static Singleton1 Instance
        {
            get
            {
                if (instance==null)
                {
                    instance = new Singleton1();
                }
                return instance;
            }
        }
    }
}

评注:
对于线程来说不安全
单线程中已满足要求

优点:
由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能
直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。惰性实例化避免了在应用程序启动时实例化不必要的 singleton。

2. 线程安全

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 
 5 namespace Singleton
 6 {
 7     public sealed class Singleton2
 8     {
 9         private static Singleton2 instance = null;
10         private static readonly object padlock = new object();
11         Singleton2() { }
12         public static Singleton2 Instance
13         {
14             get
15             {
16                 lock(padlock)
17                 {
18                     if (instance==null)
19                     {
20                         instance = new Singleton2();
21                     }
22                     return instance;
23                 }
24             }
25         }
26     }
27 }

评注:
同一个时刻加了锁的那部分程序只有一个线程可以进入
对象实例由最先进入的那个线程创建
后来的线程在进入时(instence == null)为假,不会再去创建对象实例
增加了额外的开销,损失了性能

3. 双重锁

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 
 5 namespace Singleton
 6 {
 7     /// <summary>
 8     /// 单例模式-双重锁
 9     /// </summary>
10     public sealed class Singleton3
11     {
12         //定义静态变量来保存类实例
13         private static Singleton3 instance = null;
14         //定义一个标识,确保线程同步
15         private static readonly object padlock = new object();
16         //定义私有构造函数,使外界不能创建该实例
17         private Singleton3() { }
18         //定义公有属性提供一个全局点
19         public static Singleton3 Instance
20         {
21             // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
22             // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
23             // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
24             // 双重锁定只需要一句判断就可以了
25             get
26             {
27                 if (instance==null)
28                 {
29                     lock(padlock)
30                     {
31                         if (instance==null)
32                         {
33                             instance = new Singleton3();
34                         }
35                     }
36                 }
37                 return instance;
38             }
39         }
40     }
41 }

评注:
多线程安全
线程不是每次都加锁
允许实例化延迟到第一次访问对象时发生

4. 静态初始化

using System;
using System.Collections.Generic;
using System.Text;

namespace Singleton
{
    public sealed class Singleton4
    {
        private static readonly Singleton4 instance = new Singleton4();
        static Singleton4() { }
        private Singleton4() { }
        public static Singleton4 Instance
        {
            get { return instance; }
        }
    }
}

评注:
依赖公共语言运行库负责处理变量初始化
公共静态属性为访问实例提供了一个全局访问点
对实例化机制的控制权较少(.NET代为实现)
静态初始化是在 .NET 中实现 Singleton 的首选方法

5. 延迟初始化

using System;
using System.Collections.Generic;
using System.Text;

namespace Singleton
{
    public sealed class Singleton5
    {
        private Singleton5() { }
        public static Singleton5 Instance
        {
            get
            {
                return Nested.instance;
            }
        }

        private class Nested
        {
            static Nested() { }
            internal static readonly Singleton5 instance = new Singleton5();
        }
    }
}

评注:
初始化工作由Nested类的一个静态成员来完成,这样就实现了延迟初始化。

6. 使用.NET4.0 Lazy<T>

using System;
using System.Collections.Generic;
using System.Text;

namespace Singleton
{
    public sealed class Singleton6
    {
        private static readonly Lazy<Singleton6> lazy =
            new Lazy<Singleton6>(() => new Singleton6());
        public static Singleton6 Instance
        {
            get
            {
                return lazy.Value;
            }
        }

        private Singleton6() { }

    }
}

评注:

简单,性能好,可以通过IsValueCreated检测实例是否已经创建。

posted @ 2019-01-19 18:48  星空天宇  阅读(117)  评论(0编辑  收藏  举报