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

有帮助吗?

解决方案

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

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

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

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

其他提示

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

这里更详细地说明为什么单身人士不好, Steve Yegge。基本上你不应该在几乎所有情况下使用单身人士,你不可能真的知道它不会在不止一个地方需要。

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

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

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

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

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

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

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

这是我朋友Alex的咆哮米勒......它没有完全列举“当你不应该使用单身人士”时但它是一个全面的,优秀的帖子,并且认为在极少数情况下应该只使用单例,如果有的话。

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

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

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

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

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

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

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

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

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

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

// 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
{
};

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top