1、单件模式简介 1、单件模式简介 1.1>、定义 单件模式(Singleton)定义:要求一个类有且仅有一个实例,并且提供了一个全局的访问点,在同一时刻只能被一个线程所访问。 单件模式的特点: 1.2>、使用频率 中高 1.3>、单件模式应用 2>、Word文档在同一时间内,只能有一个用户对其进行操作,程序设计中需要保证一个文档不能被两个用户同时写入。 2、单件模式结构 2.1>、结构图 2.2>、参与者 单件模式参与者: Singleton ° 被调用的单件对象; ° 在单件模式中,通常由Instance()或GetInstance()方法负责对象的创建,该方法应保证每个需要(单件)对象的客户端均能访问。 3、单件模式结构实现 C#单件模式实现要点: 单件类有一个私有的无参构造函数,这可以防止被其他类实例化,而且单例类也不应该被继承,如果单例类允许继承那么每个子类都可以创建实例,这就违背了单件模式的“唯一实例”原则。 单件类使用sealed修饰,可以阻止被继承。 使用一个静态的变量用来保存单实例的引用。 使用一个公有的静态方法用来获取单一实例的引用,如果实例为null即创建一个。 1>、非线程安全 Singleton.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.SingletonPattern.Structural { /// <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; using DesignPatterns.SingletonPattern.Structural; namespace DesignPatterns.SingletonPattern { class Program { static void Main(string[] args) { // 创建一个实例s1 Singleton s1 = Singleton.Instance(); // 创建一个实例s2 Singleton s2 = Singleton.Instance(); if (s1 == s2) { Console.WriteLine("对象为相同实例"); } } } } 运行输出: 对象为相同实例
请按任意键继续. . . 实践中Word文档在同一时间内,只能一个用户对其进行写操作实例。 Singleton.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.SingletonPattern.Practical { /// <summary> /// Word文档在同一时间内,只能有一个用户对其进行操作,需要保证一个文档不能被两个用户同时写入。 /// </summary> public sealed class Singleton { private static Singleton _instance; // 将构造函数设为private,防止通过new实例化对象 private Singleton() { } // 获取实例,并加入判断逻辑,保证实例只被创建一次 public static Singleton Instance() { // 使用延迟初始化 // 注: 非线程安全 if (_instance == null) { _instance = new Singleton(); Console.WriteLine("Word文档打开成功,具有读写权限"); } else { Console.WriteLine("Word文档已经被锁定,不可写入"); } return _instance; } } } Program.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.SingletonPattern.Practical; namespace DesignPatterns.SingletonPattern { class Program { static void Main(string[] args) { // 创建一个实例s1 Singleton s1 = Singleton.Instance(); // 创建一个实例s2 Singleton s2 = Singleton.Instance(); Console.ReadKey(); } } } 运行输出: Word文档打开成功,具有读写权限
Word文档已经被锁定,不可写入 以上的实现方式适用于单线程环境,在多线程的环境下有可能得到Singleton类的多个实例。假如同时有两个线程去判断(null == _singleton),并且得到的结果为真,那么两个线程都会创建类Singleton的实例,这样就违背了Singleton模式“唯一实例”的原则。 2>、简单线程安全 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.SingletonPattern.Structural { 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模式由于使用静态成员存储类实例,所以可能会造成资源无法及时释放。 单件模式适用情形: 1>、当类只能有一个实例而且客户可以从一个众所周知的访问点访问时; 2>、当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能适用一个扩展的实例时。 单件模式具有以下特点: 1>、实例控制:Singleton会阻止其他对象实例化其自己的Singleton对象的副本,从而确保所有对象都访问唯一实例; 2>、额外的开销:虽然很小,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销; 3>、可能的开发混淆:使用Singleton对象时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类; 4>、对象的生存期问题:Singleton不能解决删除单个对象的问题。在提供内存管理的语言中(如.Net Framework的语言),只有Singleton类能够导致实例被取消分配,因为它包含该对象实例的私有引用。在某些语言中(如C++),其他类可以删除对象实例,但这样会导致Singleton类中出现悬浮引用。 5、参考资料 |
|
来自: 雪柳花明 > 《完整的一套设计模式C#纯摘抄》