这是滥用单身人士吗?

时间:2014-05-22 22:05:47

标签: c# design-patterns singleton

我已经阅读了所有关于单身人士以及他们如果被滥用而构成反模式的威胁。因此,我希望得到第二个意见,即这是否是对模式的滥用。

基本上我有5个存储库。他们所做的就是存储数据。实际上,他们存储的所有数据都是密切相关的,我只为他们制作了5个不同的存储库,因此这些类很简单,易于查看。我知道,如果我将这些存储库中的每一个都设为单例,我就可以对任何可维护的单元测试说再见;然而;我有这个想法,我可以使每个存储库成为一个普通的类,然后创建一个单独存储每个存储库的1个副本。

通过这种方式,我可以满足每个程序实例只有一个中心位置的要求,但我也可以在需要执行的一些操作中对每个存储库进行单元测试。

2 个答案:

答案 0 :(得分:2)

当然,您可以对存储库进行单元测试,但是您肯定会很难对依赖于这些存储库的所有其他代码进行单元测试。 Singleton通过遍布代码库的直接访问将调用代码耦合到一对一实现。即使确实有一个数据副本,即某种内存数据库,也没有理由让其他层知道这一点。

此外,通过“使它们成为一个简单的类”(我认为你的意思是,通过公开一个公共构造函数?),你正在击败单例的整个观点,即没有其他代码可以实例化不同实例的概念。

如果存储库是某个类的依赖项,那么只需使用构造函数注入传递它们,并使您的测试更容易。这将允许您在从域层测试类时轻松模拟每个存储库。

答案 1 :(得分:0)

什么构成滥用单身人士(或根本就是整体有用性)是那些没有明确答案的宗教论据之一。

但是,你已经遇到了单例模式的一个主要缺点,那就是它使单元测试变得复杂。更糟糕的是,它通常会降低代码的整体可维护性。

考虑这种可能的替代品;

   public interface IRepositoryContainer
   {
      IRepository GetRepository<T>() where T : IRepository;
   }

   public partial class App : Application, IRepositoryContainer
   {
      private List<IRepository> repositories =
         new List<IRepository>() { new MyRespository() };

      public IRepository GetRepository<T>() 
         where T : IRepository
      {
         return repositories.Where(t => t is T).SingleOrDefault();
      }

然后在你之前调用单身人士的地方,而不是......

     IRepository repo = (Application.Current as IRepositoryContainer).GetRepository<MyRespository>();

只是一个想法,但是只有一个应用程序实例,接口可以帮助您解决这个问题。

(是的,上面的示例代码是wpf,但是主体应该适用)