假设您有一个与数据库交互的系统。由于系统如此严重地使用数据库,因此几乎每个子程序都遵循以下模式:
foo(database, rest, of, arguments)
很快就注意到了,因为foo是一个更大的对象的一部分,所以连接变量被移动到一个对象变量。不幸的是,这意味着每个模型对象的构造函数都接受这个参数。
因此,您决定创建一个可以生成与数据库连接的模块。由于与数据库的连接很昂贵,因此缓存连接并在将来的调用中返回缓存的值。
你刚刚创造的是一个单身人士。这种模式在开发社区中普遍不赞成。再说一次,DRY是一个受鼓励的原则,甚至比不鼓励单身模式更为重要。
哪个更好?您的选项是膨胀每个函数调用(或至少构造函数)或创建单例的参数数量。有没有第三种选择,我没有看到?
编辑:反对单身人士的文章是http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx。我认为那里提出的论点是有道理的,我希望反单身人士阵营可以解决这个设计问题。
答案 0 :(得分:2)
DRY是方式,方式比“不要使用单身人士”更重要,如果任何人都实际明确表达任何这样的原则(而不是说,“不要滥用单身人士) “)。如果你愿意,如果你愿意,可以随意满足,但如果你必须只满足一个,请满足DRY。
答案 1 :(得分:1)
您可能还会考虑查找或注入模式。使用连接详细信息创建一个单例,然后让任何需要连接的类使用“查找”或创建系统将其注入到类中。如果滥用可能导致问题,但对于共享资源,这些方法对我来说很有意义。
答案 2 :(得分:0)
单用作为将全局变量引入系统的方法被认为是不好的。
实现为static
个变量的单身人士很糟糕,因为他们无法轻易模拟出来进行测试。作为静态,他们不会被注入,这隐藏了依赖性。您现在正在进行的讨论是由您在代码中看到这种依赖性而引发的。那样太好了!您正在通过尝试寻找更好的设计来聆听代码并做出反应。如果数据库访问是通过静态入口点,您就不会注意到依赖性扩散。
使用类的单个共享实例(通常作为服务)的几个对象的概念是完全有效的设计。以这种方式思考,所有服务对象最终都成为一种“范围单例”。 I.E.在这个子系统中,只有一个X实例。正确实现这是一个布线决策,而不是类实现决策。 I.E.你可以使用任何一个类作为一个单独的类,只需要创建一个并将同一个实例传递给任何想要一个的人......所讨论的类不知道它是一个单例。
我同意你的看法,将'数据库'传递给很多对象是一种气味。我会将对“数据库”的所有调用都计入强类型的Repository对象,每个对象都有一个干净的接口,让调用者可以询问它想要的数据集,而不必担心如何检索数据或将其转换为域对象。然后,我会将所需的存储库注入以前使用数据库的类的构造函数中,而不是在每次调用时传递它。如果您正在进行“依赖注入”,您会发现布线代码移动到对象之外,进入工厂类。然后,这些工厂只会将存储库注入实际需要查询存储库的类中。
我看到的一个模式是对象获得他们并不真正需要的依赖,因为他们反过来将它传递给他们创建的其他对象。通过将这种“工厂”行为分解为它自己的类来防止这种情况。
无论如何..简短的回答是“继续挖掘......找出为什么这么多类需要数据库访问,应用单一责任原则和依赖注入来限制传播”。