Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Language agnostic 滥用singleton类的最常见示例_Language Agnostic_Design Patterns_Singleton - Fatal编程技术网

Language agnostic 滥用singleton类的最常见示例

Language agnostic 滥用singleton类的最常见示例,language-agnostic,design-patterns,singleton,Language Agnostic,Design Patterns,Singleton,什么时候不应该使用singleton类,尽管这样做可能非常诱人?如果我们有一份我们应该注意避免的最常见的“单发性扁桃体炎”的清单,那就太好了。我知道很多人的回答是“当你有多个”等等 因为最初的海报想要一个不应该使用单件的案例列表(而不是最主要的原因),我会附和: 无论何时使用它,因为不允许使用全局密码 我有过多少次初级工程师因为知道我在代码评审中不接受全局代码而使用单例代码。当我指出他们所做的只是用一个单一模式取代了一个全局模式,而他们仍然只有一个全局模式时,他们似乎经常感到震惊 对于可能演变成

什么时候不应该使用singleton类,尽管这样做可能非常诱人?如果我们有一份我们应该注意避免的最常见的“单发性扁桃体炎”的清单,那就太好了。

我知道很多人的回答是“当你有多个”等等

因为最初的海报想要一个不应该使用单件的案例列表(而不是最主要的原因),我会附和:

无论何时使用它,因为不允许使用全局密码


我有过多少次初级工程师因为知道我在代码评审中不接受全局代码而使用单例代码。当我指出他们所做的只是用一个单一模式取代了一个全局模式,而他们仍然只有一个全局模式时,他们似乎经常感到震惊

对于可能演变成可复用资源的东西,不要使用单例

这听起来可能很傻,但如果你宣布某个东西是单身,你就在强烈声明它绝对是独一无二的。您正在围绕它构建代码,越来越多。当你在数千行代码之后发现它根本不是一个单体时,你面前有大量的工作要做,因为所有其他对象都期望WizBang类的神圣对象是一个单体

典型示例:“此应用程序只有一个数据库连接,因此它是一个单实例。”-坏主意。您可能希望将来有多个连接。最好创建一个数据库连接池,并用一个实例填充它。行为类似于单例,但所有其他代码都将具有用于访问池的可增长代码


编辑:我知道理论上可以将一个单体扩展为多个对象。然而,没有真正的生命周期(如池化/取消池化),这意味着已经分发的对象没有真正的所有权,也就是说,现在的多单例必须是无状态的,才能由不同的方法和线程同时使用。

单例在大多数情况下只是使事物保持静态。所以你要么实际上是让数据成为全局的,我们都知道全局变量是坏的,要么你写的是静态方法,这不是很面向对象的,是吗


史蒂夫·耶格(Steve Yegge)更详细地讲述了为什么单身汉不好。基本上,你不应该在几乎所有的情况下都使用单例,你不可能真正知道它永远不会在一个以上的地方被需要。

几年前,我为一个大的单例感到内疚(谢天谢地,我从那时起就学会了单例)

发生的事情是,我参与了一个桌面应用程序项目,该项目已从VB6转换为.Net,真是一团糟。比如40页(打印)函数,没有真正的类结构。我构建了一个类来封装对数据库的访问。还不是真正的数据层,只是一个真正的数据层可以使用的基类。在某个地方,我有了一个好主意,让这个班成为单身学生。它正常工作了一年左右,然后我们还需要为应用程序构建一个web界面。由于所有web用户必须共享同一个连接,因此单例最终成为数据库的一个巨大瓶颈。再一次。。。吸取的教训


回顾过去,它可能在短时间内实际上是正确的选择,因为它迫使其他开发人员在使用它时更加严格,并使他们意识到范围界定问题,而这在VB6世界中以前不是一个问题。但我应该在几周后把它改回来,否则我们周围的建筑会太多。

让它成为噩梦的一件事是,它是否包含可修改的全球状态。我在一个项目中工作过,那里到处都使用单子来解决本应以完全不同的方式解决的问题(传入策略等)。在某些情况下,“去单子化”是对系统部分的重大重写。我想说的是,在大多数情况下,当人们使用单例时,这是错误的b/c它一开始看起来不错,但在测试中会变成一个问题。

有时,你假设某件事只有一个,然后你就错了

例如,一个数据库类。您假设您将只连接到应用程序的数据库

// Its our database! We'll never need another
class Database
{
};
但是等等!你的老板说,连接其他人的数据库。假设您希望将phpbb添加到网站,并希望插入其数据库以集成其部分功能。我们应该创建一个新的singleton还是另一个数据库实例?大多数人都认为最好使用同一类的新实例,因为没有代码重复

你宁愿

Database ourDb;
Database otherDb;
然后复制过去的数据库并制作:

// Copy-pasted from our home-grown database.
class OtherGuysDatabase
{
};

这里的危险在于,您可能不再考虑创建新的类实例,而是开始考虑每个实例都有一个类型

当多个应用程序在同一JVM中运行时


单例是整个JVM中的单例,而不仅仅是单个应用程序。即使多个线程或应用程序似乎正在创建一个新的singleton对象,但如果它们运行在同一个JVM中,它们都在使用同一个对象。

singleton实际上总是一个坏主意,通常是无用的/冗余的,因为它们只是一个体面模式的非常有限的简化

查看依赖项注入是如何工作的。它解决了同样的问题,但以一种更有用的方式——事实上,您发现它适用于设计的更多部分


尽管您可以在那里找到DI库,但您也可以自己创建一个基本的DI库,这非常简单。

我尝试只创建一个单例—控制/服务定位器对象的反转

IService service = IoC.GetImplementationOf<IService>();
IService服务=IoC.GetImplementationOf();
我的朋友亚历克斯·米勒。。。这篇文章并没有具体列举“什么时候不应该使用单身汉”,但它是一篇综合性的、优秀的文章,并且认为应该只使用我们