Design patterns 单身还是干的

Design patterns 单身还是干的,design-patterns,singleton,dry,Design Patterns,Singleton,Dry,假设您有一个与数据库交互的系统。由于系统大量使用数据库,几乎每个子例程都遵循以下模式: foo(database, rest, of, arguments) 这一点很快就被注意到了,因为foo是更大对象的一部分,所以连接变量被移动到一个对象变量。不幸的是,这意味着每个模型对象的构造函数都接受这个参数 因此,您决定创建一个可以生成到数据库的连接的模块。由于到数据库的连接很昂贵,因此会缓存该连接,并在以后的调用中返回该缓存值 您刚刚创建的是一个单例。这是发展界普遍不赞成的一种模式。再说一次,DRY

假设您有一个与数据库交互的系统。由于系统大量使用数据库,几乎每个子例程都遵循以下模式:

foo(database, rest, of, arguments)
这一点很快就被注意到了,因为foo是更大对象的一部分,所以连接变量被移动到一个对象变量。不幸的是,这意味着每个模型对象的构造函数都接受这个参数

因此,您决定创建一个可以生成到数据库的连接的模块。由于到数据库的连接很昂贵,因此会缓存该连接,并在以后的调用中返回该缓存值

您刚刚创建的是一个单例。这是发展界普遍不赞成的一种模式。再说一次,DRY是一个受鼓励的原则,甚至比单身模式更受鼓励

那么哪一个更好呢?您的选项是增加每个函数调用(或者至少是构造函数)的参数数量,或者创建一个单例。还有第三种选择我没有看到吗


编辑:反对单身汉的文章是。我认为这里提出的论点是有道理的,我希望反单身阵营能够解决这个设计问题。

如果任何人真的阐述过任何这样的原则(比如说,“不要可怕地滥用单身”),那么干的方式比“不使用单身”更重要。如果你愿意,如果你愿意,可以自由满足两者,但是如果你只满足一个,满足干燥。

< P>你也可以考虑查找或注入模式。创建一个具有连接详细信息的单例,然后让任何需要连接的类使用“查找”或创建一个系统将其注入到您的类中。如果滥用会导致问题,但对于共享资源,这些方法对我来说很有意义。

当使用单例作为将全局变量引入系统的方法时,它们被认为是不好的

作为
静态
变量实现的单例是不好的,因为它们不容易模拟出来进行测试。由于是静态的,它们不会被注入,从而隐藏了依赖性。您现在进行的讨论是因为您在代码中看到了这种依赖关系。太好了!您正在倾听代码,并通过尝试找到更好的设计作出反应。如果数据库访问是通过一个静态入口点进行的,您就不会注意到依赖性的扩散

多个对象使用一个类的单个共享实例(通常作为服务)的概念是完全有效的设计。以这种方式考虑,所有服务对象最终都是一种“作用域单例”。也就是说,在这个子系统中,只有一个X实例被正确实现。这是一个布线决策,而不是类实现决策。也就是说,您可以通过只创建一个类并将同一实例传递给任何想要一个类的人来将任何类作为一个单例使用。。。有问题的班级不知道这是单身

我同意你的观点,将“数据库”传递给许多对象是一种气味。我会将对“数据库”的所有调用分解为强类型存储库对象,每个对象上都有一个干净的接口,允许调用方请求它想要的数据集,而不必担心如何检索或转换为域对象。然后,我会将所需的存储库注入到以前使用数据库的类的构造函数中,而不是在每次调用时传递它。如果您正在执行“依赖项注入”,您会发现连接代码会从对象移动到工厂类中。然后,这些工厂将只将存储库注入到实际需要查询存储库的类中

我看到的一种模式是,对象获得了一个它们并不真正需要的依赖项,因为它们反过来会将它传递给它们创建的其他对象。这是通过将这种“工厂”行为分解到它自己的类中来防止的


无论如何。。简短的回答是“继续挖掘..找出为什么这么多类需要数据库访问,应用单一责任原则和依赖注入来限制扩展”.

如果你不能说出一个更好的理由不使用单例模式,而不是那些你不认识的人,他们没有参与你的开发过程,对此发出非特异性的愤怒声音,我不明白为什么不使用它。设计模式分析的存在是为了帮助您完成工作,而不是强制执行对时尚性的任意规定。(并不是说你更具体地说明了为什么推荐DRY,但它解决的问题是任何傻瓜都会看到的糟糕的事情。)这里的每个人都有一堆“规则”,应该“永远”不被违反,如果你把它们放在一起,就永远不会写出一行代码。这很公平,我可以更具体地说明我的理由。我正在编辑这篇文章,以包含每一篇文章的原因链接。这个建议与我目前使用的非常接近。故事是我如何设计的,然后有人说“嘿,这是一个单例,不是很糟糕吗?”半个小时的谷歌搜索,然后这个问题,我们来了。是的,依赖注入是一个很好的方法,可以避免在这种情况下使用单例,给出正确的上下文。如果您有某种顶级应用程序模型,您可以将数据库连接存储为该模型的属性,而不是类变量,现在每个人都很高兴。公平点,但您仍然需要传递应用程序模型,所以我们处于同一条船上。@lackita:不一定;这完全取决于您的体系结构。让应用程序依次使用DI将对自身的引用推送到它生成的模型中,以完成实际工作,并消除传递。你能解释一下DI是什么吗?