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

先来看看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 Dispatcher
2     {
3         public static T BuildObject<T>() where T : class
4         {
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 MapHelper
13         {
14             get { return mapHelper; }
15         }
16 
17         public PathHelper PathHelper
18         {
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     }

 

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


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

 

 

 

posted @ 2015-01-12 15:04  起点2014  阅读(676)  评论(2编辑  收藏  举报