首页 > 代码库 > 重构:将单例模式从业务类中完全解耦

重构:将单例模式从业务类中完全解耦

先来看看Singleton的用例图:

技术分享

在一个实际的老项目中,有很多的业务类,也不知道当时如何设计的,这些业务类均被设计成了Singleton模式。

项目中这些业务类结构如下:

技术分享

而每个业务类的设计均为单例,诸如:

public class SearchHelper    {        private object obj = new object();        private static SearchHelper search;        private SearchHelper(){}        public static SearchHelper Instance        {            get            {                if (search == null)                {                    lock (obj)                    {                        if (search == null)                            search = new SearchHelper();                    }                }                return search;            }        }        public string GetSearch()        {            return "Path";        }    }


这种设计初初一看,就不是很顺眼。

这种业务类和单例本身强结合的模式,实际应用中,还真带来了一些麻烦,比如这个SearchHelper, 我有时候需要对某些方法获取更新某实体后的值,因其单例类模式,直接就无法得到其值,只好绕弯路。

于是重构这个模块,已经是摆在面前。 当然也可以不去重构,让代码继续乱下去,乱下去,乱下去,直到死亡 :-)

 

经过一番考虑,首先想到的是将这些业务类和单例这个模式强结合的模式分离, 分离后让单例不再强奸这些业务类。

 

于是,就有了下文:

第一步:将这些业务类的单例去除,出除后,代码结构如下:

public class SearchHelper {     private SearchHelper(){}      public string GetPath()      {          return "Path";      } }

同理,去除其他所有的业务类的单例。
PathHelper:

public class PathHelper{  private PathHelper(){}   public string GetPath()   {       return "Path";   }
}

MapHelper: 

 public class MapHelper {
  private MapHelper(){}
public string GetMap() { return "Map"; } }

 

第二步:定义个单例专用类,定义一个泛型类,并利用反射特性使其能够动态按需创建单例

 public class Singleton<T> where T : class    {        static Mutex mutex = new Mutex();        static T instance;        private Singleton() { }        public static T UniqueInstance        {            get            {                mutex.WaitOne();        // enter protected area                if (instance == null)                {                    try                    {                        instance = SingletonCreator.instance;                    }                    catch (Exception ex)                    {                        throw ex;                    }                }                mutex.ReleaseMutex();   // exit protected area                return instance;            }        }        class SingletonCreator        {            static SingletonCreator() { }            // Private object instantiated with private constructor            internal static readonly T instance = CreateNewInstance();            private static T CreateNewInstance()            {                //Get the current assembly object                Assembly assembly = Assembly.GetExecutingAssembly();                // Retrieve assembly types                Type[] types = assembly.GetTypes();                foreach (Type typeName in types)                {                    Module typeMod = assembly.GetModule(typeName.ToString());                    if (typeof(T).IsAssignableFrom(typeName) && (typeName.IsClass))                    {                        // Create and return an instance of the appropriate model object                        return Activator.CreateInstance(typeName) as T;                    }                }                throw new Exception("New instance not found!");            }        }    }


第三步: 定义一个Dispatcher类,用以得到泛型类的单例。

1  public class Dispatcher2     {3         public static T BuildObject<T>() where T : class4         {5             return Singleton<T>.UniqueInstance;6         }7     }


第四步: 定义一个Facades类,用以得到想要的具体的某业务类的单例。

 1  public class Facades   2     { 3         private static SearchHelper searchHelper; 4         private static  MapHelper mapHelper; 5         private static  PathHelper pathHelper; 6  7         public SearchHelper SearchHelper 8         { 9             get { return searchHelper; }10         }11 12         public MapHelper MapHelper13         {14             get { return mapHelper; }15         }16 17         public PathHelper PathHelper18         {19             get { return pathHelper; }20         }21         public Facades()22         {23             searchHelper = Dispatcher.BuildObject<SearchHelper>();24             mapHelper = Dispatcher.BuildObject<MapHelper>();25             pathHelper = Dispatcher.BuildObject<PathHelper>();26         }       27     }

 

好了,到此为止,已经将单例模式从业务类中完全解耦。


业务类就是业务来,单例就是单例,无需将单例强加在业务类上。重构后,其文件结构如下:

 

 技术分享

 

重构:将单例模式从业务类中完全解耦