现在的位置: 首页 > 综合 > 正文

C#设计模式系列:单件模式(Singleton)

2012年05月16日 ⁄ 综合 ⁄ 共 2470字 ⁄ 字号 评论关闭

1、单件模式简介

  单件模式(Singleton)定义:要求一个类有且仅有一个实例,并且提供了一个全局的访问点。

  单件模式的特点:
  1>、单件类只能有一个实例。
  2>、单件类必须自身创建唯一实例。
  3>、单件类必须给所有其它对象提供唯一实例。

  单件模式应用:
  1>、每台计算机可以有若干个打印机,但只能有一个Printer Spooler,避免两个打印作业同时输出到打印机。

2、单件模式结构

3、单件模式实现

   C#单件模式实现要点:

  ◊ 单件类有一个私有的无参构造函数,这可以防止被其他类实例化,而且单例类也不应该被继承,如果单例类允许继承那么每个子类都可以创建实例,这就违背了单件模式的“唯一实例”原则。

  ◊ 单件类使用sealed修饰,可以阻止被继承。

  ◊ 使用一个静态的变量用来保存单实例的引用。

  ◊ 使用一个公有的静态方法用来获取单一实例的引用,如果实例为null即创建一个。

 

  C#单件模式常见的6种实现方式:

  1>、非线程安全

  Singleton.cs

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

namespace DesignPatterns.SingletonPattern.First
{
    /// <summary>
    /// 单件模式实现方式一,由于该实现方式非线程安全,在实际应用中不推荐使用。
    /// </summary>
    public sealed class Singleton
    {
        private static Singleton _instance;

        // 将构造函数设为private,防止通过new实例化对象
        private Singleton()
        {
        }

        public static Singleton Instance()
        {
            // 使用延迟初始化
            // 注: 非线程安全
            if (_instance == null)
            {
                _instance = new Singleton();
            }

            return _instance;
        }
    }
}

  Program.cs

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

namespace DesignPatterns.SingletonPatternApp
{
    class Program
    {
        static void Main(string[] args)
        {
            DesignPatterns.SingletonPattern.First.Singleton s1 = DesignPatterns.SingletonPattern.First.Singleton.Instance();
            DesignPatterns.SingletonPattern.First.Singleton s2 = DesignPatterns.SingletonPattern.First.Singleton.Instance();

            if (s1 == s2)
            {
                Console.WriteLine("对象为相同实例。");
            }
        }
    }
}

   以上的实现方式适用于单线程环境,在多线程的环境下有可能得到Singleton类的多个实例。假如同时有两个线程去判断(null == _singleton),并且得到的结果为真,那么两个线程都会创建类Singleton的实例,这样就违背了Singleton模式“唯一实例”的原则。

   2>、简单线程安全

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

namespace DesignPatterns.SingletonPattern.Second
{
    public sealed class Singleton
    {
        private static Singleton _instance;

        // Lock synchronization object
        private static readonly object _syncLock = new object();

        // Constructor is 'private'
        private Singleton()
        {
        }

        public static Singleton Instance()
        {
            // Support multithreaded applications through
            // 'Double checked locking' pattern which (once
            // the instance exists) avoids locking each
            // time the method is invoked
            if (_instance == null)
            {
                lock (_syncLock)
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                }
            }

            return _instance;
        }
    }
}

  以上方式的实现方式是线程安全的,首先创建了一个静态只读的进程辅助对象,由于lock是确保当一个线程位于代码的临界区时,另一个线程不能进入临界区(同步操作)。如果其他线程试图进入锁定的代码,则它将一直等待,直到该对象被释放。从而确保在多线程下不会创建多个对象实例了。但这种实现方式要进行同步操作,将影响系统性能的瓶颈和增加了额外的开销。

 

4、单件模式总结

  使用注意点:

  1>、不要使用单例模式存取全局变量。这违背了单例模式的用意,最好放到对应类的静态成员中。

  2>、不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能及时释放连接。Singleton模式由于使用静态成员存储类实例,所以可能会造成资源无法及时释放。

5、参考资料

http://csharpindepth.com/Articles/General/Singleton.aspx

http://www.dofactory.com/Patterns/Patterns.aspx

抱歉!评论已关闭.