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、参考资料