设计模式系列一创建型之(单件模式)
1、意图
- 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2、适用性
- 当类只有一个实例而且客户可以从一个众所周知的访问点访问它时。
- 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
3、示意代码
public class Singleton { private static Singleton instance; /// <summary> /// 程序运行时,创建一个静态只读的进程辅助对象 /// </summary> private static readonly object _object = new object(); /// <summary> /// 构造方法私有,外键不能通过New类实例化此类 /// </summary> private Singleton() { } /// <summary> /// 此方法是本类实例的唯一全局访问点 /// (双重加锁 Double-Check Locking) /// </summary> /// <returns></returns> public static Singleton GetInstance() { //先判断实例是否存在,不存在再加锁处理 if (instance == null) { //在同一时刻加了锁的那部分程序只有一个线程可以进入, lock (_object) { //如实例不存在,则New一个新实例,否则返回已有实例 if (instance == null) { instance = new Singleton(); } } } return instance; } }
4、实际应用
场景:要求对发送的消息做记录,同一时间内只允许一个进程对Txt文件的访问;
/// <summary> /// MsgLog类 /// </summary> public class MsgLog { private static object _helper = new object(); private static MsgLog _instance; private static object _fileLock = new object(); private MsgLog() { } public static MsgLog GetInstance() { lock (_helper) { if (_instance == null) { _instance = new MsgLog(); } } return _instance; } /// <summary> /// 消息记录 /// </summary> public void SendMsgLog(string msg) { string filePath = System.AppDomain.CurrentDomain.BaseDirectory + "mail.txt"; StreamWriter sw = null; FileStream fs = null; lock (_fileLock) { fs = !File.Exists(filePath) ? System.IO.File.Create(filePath) : new FileStream(filePath, FileMode.Append); sw = new StreamWriter(fs, Encoding.UTF8); sw.WriteLine("================================"); sw.WriteLine(msg); sw.Flush(); sw.Close(); } } }
客户端调用:
static void Main(string[] args) { MsgLog email1 = MsgLog.GetInstance(); email1.SendMsgLog("发消息给迁梦余光......"); MsgLog email2 = MsgLog.GetInstance(); email2.SendMsgLog("再次发消息给迁梦余光......"); }
执行结果: