最常见的滥用单身人士的例子

时间:2008-09-25 19:12:16

标签: language-agnostic design-patterns singleton

什么时候不应该使用单身课,尽管这样做可能很诱人?如果我们列出了最常见的“单发性炎症”,我们应该注意避免,这将是非常好的。

11 个答案:

答案 0 :(得分:9)

不要将单例用于可能演变成可倍增资源的东西。

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

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

编辑:据我所知,理论上你可以将单例扩展为多个对象。然而,没有真正的生命周期(如汇集/解放),这意味着没有真正的所有权已经分发出来,即现在的多单身必须是无状态的,可以通过不同的方法和线程同时使用。 / p>

答案 1 :(得分:6)

大多数情况下,单身人士只是让事情变得静止。所以你要么实际上使数据全局化,要么我们都知道全局变量是坏的,或者你正在编写静态方法,那现在不是很好吗?

Here是史蒂夫·叶格(Steve Yegge)更为详细的关于为什么单身人士不好的咆哮。基本上你不应该在几乎所有情况下使用单身人士,你不可能真的知道它不会在不止一个地方需要。

答案 2 :(得分:3)

我知道很多人已经回答“当你有一个以上”等等。

由于原始海报想要一个你不应该使用单身人士的案例清单(而不是最重要的原因),我会说:

每当您使用它时,因为您不允许使用全局!

我使用过Singleton的初级工程师的次数,因为他们知道我在代码评论中不接受全局变量。当我指出他们所做的只是用Singleton模式取代全局并且他们仍然只有一个全局时,他们常常感到震惊!

答案 3 :(得分:2)

几年前我对一个大个子感到内疚(谢天谢地,我从那时起就学会了我的内容)。

发生的事情是我加入了一个从VB6转换为.Net的桌面应用程序项目,这真是一团糟。像40页(打印)功能,没有真正的类结构。我构建了一个类来封装对数据库的访问。不是真正的数据层(还),只是真正的数据层可以使用的基类。在某个地方,我有一个明智的想法,让这个班级成为一个单身人士。它工作好一年左右,然后我们也需要为应用程序构建一个Web界面。单例最终成为数据库的一个巨大瓶颈,因为所有Web用户都必须共享相同的连接。再次......吸取教训。

回顾过去,它可能实际上是一段时间的正确选择,因为它迫使其他开发人员更加自律地使用它并使他们意识到在VB6世界中以前不存在问题的范围问题。但是我应该在几周之后将它改回来,然后我们就会在它周围积聚太多。

答案 4 :(得分:2)

Here is a rant由我的朋友亚历克斯米勒...它没有完全列举“当你不应该使用单身人士”但它是一个全面的,优秀的帖子,并争辩说,在极少数情况下应该只使用单身人士,如果有的话。

答案 5 :(得分:1)

单身人士实际上总是一个坏主意,而且通常是无用的/多余的,因为它们只是对体面模式的非常有限的简化。

查看依赖注入的工作原理。它解决了同样的问题,但是以更有用的方式 - 事实上,你发现它适用于你设计的更多部分。

虽然你可以在那里找到DI库,但你也可以自己推出一个基本库,这很容易。

答案 6 :(得分:1)

我尝试只有一个单例 - 控制/服务定位器对象的反转。

IService service = IoC.GetImplementationOf<IService>();

答案 7 :(得分:0)

其中一个让它成为噩梦的事情是它是否包含可修改的全局状态。我参与了一个项目,那里有单身人士用于各种应该以完全不同的方式解决的事情(传递策略等)。“去单一化”在某些情况下是对部分内容的重大改写。系统。我认为,在人们使用Singleton的大部分案例中,它只是错误的b / c它首先看起来不错,但特别是在测试中变成了问题。

答案 8 :(得分:0)

有时候,你会认为只会有一件事,然后你就会出错。

示例,数据库类。您假设您只会连接到应用程序的数据库。

// Its our database! We'll never need another
class Database
{
};

但是等等!你的老板说,连接其他人的数据库。假设您想要将phpbb添加到网站,并希望戳它的数据库以集成它的一些功能。我们应该创建一个新的单例还是另一个数据库实例?大多数人都认为同一类的新实例是首选,没有代码重复。

你宁愿拥有

Database ourDb;
Database otherDb;

比复制过去的数据库和make:

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

这里的滑坡是你可能不再考虑创建类的新实例,而是开始认为每个实例都有一个类型。

答案 9 :(得分:0)

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

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

答案 10 :(得分:0)

在连接的情况下(例如),你不想让连接本身成为一个单独的,你可能需要四个连接,或者你可能需要销毁和重新创建一些连接是有意义的。次。

但为什么不通过单一界面(即连接管理器)访问所有连接?