单例模式是是常用经典十几种设计模式中最简单的。.NET中单例模式的实现也有很多种方式。下面我来介绍一下NopCommerce中单例模式实现。
我之前的文章就分析了一下nop中EngineContext的实现。EngineContext是把一个Web请求用Nop的EngineContext引擎上下文封装。里面提供了一个IEngine的单例对象的访问方式。
下面就是EngineContext的源码:
1 using System.Configuration; 2 3 using System.Runtime.CompilerServices; 4 5 using Nop.Core.Configuration; 6 7 8 9 namespace Nop.Core.Infrastructure 10 11 { 12 13 /// <summary> 14 15 ///Provides access to the singleton instance of the Nop engine. 16 17 ///提供了访问单例实例Nop引擎 18 19 /// </summary> 20 21 public class EngineContext 22 23 { 24 25 #region Methods 26 27 28 29 /// <summary> 30 31 /// Initializes a static instance of the Nop factory. 32 33 /// 初始化静态Nop工厂的实例 34 35 /// </summary> 36 37 /// <param name="forceRecreate">创建一个新工厂实例,尽管工厂已经被初始化</param> 38 39 [MethodImpl(MethodImplOptions.Synchronized)] 40 41 public static IEngine Initialize(bool forceRecreate) 42 43 { 44 45 if (Singleton<IEngine>.Instance == null || forceRecreate) 46 47 { 48 49 Singleton<IEngine>.Instance = new NopEngine(); 50 51 52 53 var config = ConfigurationManager.GetSection("NopConfig") as NopConfig; 54 55 Singleton<IEngine>.Instance.Initialize(config); 56 57 } 58 59 return Singleton<IEngine>.Instance; 60 61 } 62 63 64 65 /// <summary> 66 67 /// Sets the static engine instance to the supplied engine. Use this method to supply your own engine implementation. 68 69 /// 设置静态引擎实例提供的引擎, 70 71 /// </summary> 72 73 /// <param name="engine">The engine to use.</param> 74 75 /// <remarks>Only use this method if you know what you're doing.</remarks> 76 77 public static void Replace(IEngine engine) 78 79 { 80 81 Singleton<IEngine>.Instance = engine; 82 83 } 84 85 86 87 #endregion 88 89 90 91 #region Properties 92 93 94 95 /// <summary> 96 97 /// Gets the singleton Nop engine used to access Nop services. 98 99 /// </summary> 100 101 public static IEngine Current 102 103 { 104 105 get 106 107 { 108 109 if (Singleton<IEngine>.Instance == null) 110 111 { 112 113 Initialize(false); 114 115 } 116 117 return Singleton<IEngine>.Instance; 118 119 } 120 121 } 122 123 124 125 #endregion 126 127 } 128 129 }
上面Initialize方法使用[MethodImpl(MethodImplOptions.Synchronized)]声明,就保证只能有一个线程访问,因为.NET的Web程序无论是WebForm还是mvc都在服务端都是多线程的。这样就标记只能有一个线程调用Initialize方法,也就保证了实例对象IEngine的在内存中只有一份。然后把单例实例对象的存储到类Singleton中。Singleton就像是一个对象容器,可以把许多单例实例对象存储在里面。
下面我们来看看实例Singleton的实现思路。
1 using System; 2 3 using System.Collections.Generic; 4 5 6 7 namespace Nop.Core.Infrastructure 8 9 { 10 11 /// <summary> 12 13 /// A statically compiled "singleton" used to store objects throughout the 14 15 /// lifetime of the app domain. Not so much singleton in the pattern's 16 17 /// sense of the word as a standardized way to store single instances. 18 19 /// </summary> 20 21 /// <typeparam name="T">The type of object to store.</typeparam> 22 23 /// <remarks>Access to the instance is not synchrnoized.</remarks> 24 25 public class Singleton<T> : Singleton 26 27 { 28 29 static T instance; 30 31 32 33 /// <summary>The singleton instance for the specified type T. Only one instance (at the time) of this object for each type of T.</summary> 34 35 public static T Instance 36 37 { 38 39 get { return instance; } 40 41 set 42 43 { 44 45 instance = value; 46 47 AllSingletons[typeof(T)] = value; 48 49 } 50 51 } 52 53 } 54 55 56 57 /// <summary> 58 59 /// Provides a singleton list for a certain type. 60 61 /// </summary> 62 63 /// <typeparam name="T">The type of list to store.</typeparam> 64 65 public class SingletonList<T> : Singleton<IList<T>> 66 67 { 68 69 static SingletonList() 70 71 { 72 73 Singleton<IList<T>>.Instance = new List<T>(); 74 75 } 76 77 78 79 /// <summary>The singleton instance for the specified type T. Only one instance (at the time) of this list for each type of T.</summary> 80 81 public new static IList<T> Instance 82 83 { 84 85 get { return Singleton<IList<T>>.Instance; } 86 87 } 88 89 } 90 91 92 93 /// <summary> 94 95 /// Provides a singleton dictionary for a certain key and vlaue type. 96 97 /// </summary> 98 99 /// <typeparam name="TKey">The type of key.</typeparam> 100 101 /// <typeparam name="TValue">The type of value.</typeparam> 102 103 public class SingletonDictionary<TKey, TValue> : Singleton<IDictionary<TKey, TValue>> 104 105 { 106 107 static SingletonDictionary() 108 109 { 110 111 Singleton<Dictionary<TKey, TValue>>.Instance = new Dictionary<TKey, TValue>(); 112 113 } 114 115 116 117 /// <summary>The singleton instance for the specified type T. Only one instance (at the time) of this dictionary for each type of T.</summary> 118 119 public new static IDictionary<TKey, TValue> Instance 120 121 { 122 123 get { return Singleton<Dictionary<TKey, TValue>>.Instance; } 124 125 } 126 127 } 128 129 130 131 /// <summary> 132 133 /// Provides access to all "singletons" stored by <see cref="Singleton{T}"/>. 134 135 /// </summary> 136 137 public class Singleton 138 139 { 140 141 static Singleton() 142 143 { 144 145 allSingletons = new Dictionary<Type, object>(); 146 147 } 148 149 150 151 static readonly IDictionary<Type, object> allSingletons; 152 153 154 155 /// <summary>Dictionary of type to singleton instances.</summary> 156 157 public static IDictionary<Type, object> AllSingletons 158 159 { 160 161 get { return allSingletons; } 162 163 } 164 165 } 166 167 }
Singleton类里面用一个Dictionary<Type, object>()集合来存储所有的单例对象。基于Singleton类创建一些泛型类Singleton<T>,Singleton<IList<T>>,SingletonList<T>,Singleton<IDictionary<TKey, TValue>>和SingletonDictionary<TKey, TValue>。