假设您有一个与数据库交互的系统。因为系统大量使用数据库,所以几乎每个子例程都遵循这种模式:
foo(database, rest, of, arguments)
这一点很快就被注意到了,因为foo是一个更大的对象的一部分,所以连接变量被移到了一个对象变量中。不幸的是,这意味着每个模型对象的构造函数都接受这个参数。
因此,您决定创建一个可以生成到数据库的连接的模块。由于与数据库的连接开销很大,因此会对连接进行缓存,并在以后的调用中返回缓存的值。
您刚刚创建的是一个单例。这是一种在开发社区中普遍不受欢迎的模式。再说一次,DRY是一个鼓励的原则,甚至比单例模式更不受鼓励。
您的选择是增加每个函数调用(或至少是构造函数)中的参数数量,或者创建一个单例。有没有第三种选择我看不到?
编辑:反对单例的文章是http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx。我认为这里提出的论点是有道理的,我希望反独身阵营能对这个设计问题有一个解决方案。
发布于 2012-07-13 19:49:29
DRY比“不要使用单例”要重要得多,如果有人真的表达过这样的原则的话(而不是说“不要滥用单例”)。如果可以,可以同时满足这两个要求,但如果必须只满足其中一个,请满足DRY。
发布于 2012-07-13 19:51:42
您还可以考虑查找或注入模式。使用连接细节创建一个单例,然后让任何需要连接的类使用“查找”或创建一个系统将其注入到您的类中。如果滥用都会导致问题,但对于共享资源来说,这些方法对我来说很有意义。
发布于 2012-07-23 22:56:31
单例作为一种将全局变量引入系统的方式被认为是不好的。
作为static
变量实现的单例是不好的,因为它们不能很容易地模拟出来进行测试。由于是静态的,它们不会被注入,这就隐藏了依赖关系。您现在正在进行的讨论是由您在代码中看到的这种依赖项引起的。太棒了!你正在倾听代码,并试图找到更好的设计来做出反应。如果数据库访问是通过静态入口点进行的,您不会注意到依赖项的激增。
多个对象使用一个类的单个共享实例(通常作为服务)的概念是完全有效的设计。以这种方式考虑,所有服务对象最终都是一种“作用域单例”。也就是说,在这个子系统中,将只有一个X的实例。正确实现这是一个连接决策,而不是一个类实现决策。也就是说,你可以使用任何类作为单例,只需创建一个,并将相同的实例传递给任何想要一个实例的人……有问题的类不知道它是单例的。
我同意你的观点,将“数据库”传递给很多对象是一种异味。我会将对“数据库”的所有调用都分解到强类型的Repository对象中,每个对象上都有一个干净的接口,允许调用者请求它想要的数据集,而不必担心如何检索这些数据或将这些数据转换为域对象。然后,我会将所需的存储库注入到以前使用数据库的类的构造函数中,而不是在每次调用时传递它。如果你正在做“依赖注入”,你会发现连接代码移出了你的对象,进入了工厂类。然后,这些工厂将只将存储库注入实际需要查询存储库的类中。
我见过的一种模式是对象获得了它们并不真正需要的依赖,因为它们反过来将依赖传递给它们创建的其他对象。这是通过将这个“工厂”行为分解到它自己的类中来防止的。
不管怎样..。简短的答案是“继续挖掘……找出为什么这么多类需要数据库访问,应用单一责任原则和依赖注入来限制传播”。
https://stackoverflow.com/questions/11477220
复制相似问题