这个问题不是关于单身人士是否“被视为有害”。根据您的经验,我只想知道单身人士似乎运作良好的具体情况。
修改 如果你想讨论一般的单身人士的适当性和/或邪恶性,那么就会有很多问题:137975,11831
糟糕!我刚刚发现我的问题已在此处提出:On Design Patterns: When to use the Singleton?
答案 0 :(得分:7)
我们基本上将它们用于两件事:日志记录和配置。两者都假设应用程序具有中央配置和中央日志文件,并不总是有效,但在我们的大部分代码中都是如此。我们还有时会对某些工厂类或缓存类使用它们,以确保我们不会复制关键元数据。
答案 1 :(得分:4)
扩大我的评论......
问题是措辞不当,单身人士似乎在很多情况下运作良好。它应该是“单身人士不会暴露其负面特征的具体情况是什么?”简而言之,“全球变量什么时候好”?
全局变量是一个全局变量。
一旦使用
void f()
{
X* x = X::getInstance();
...
}
而不是void f(X*)
,您的意大利面条菜单已被接受。
单身人士激增,喜欢互相依赖。 SessionManager
使用使用EventManager
的{{1}}。有人希望日志文件提到当前用户的名称。 LogManager
维护者添加LogManager
,一切都是玫瑰,直到SessionManager::getInstance()->getUser()->getName();
,它还使用LoginManager
,想要记录登录失败。
单身人士抑制可测试性。
单实例属性仅在生产代码中半有用。您可能根本无法测试LogManager
函数,并且可能只会为快乐路径进行(少数)测试。
你可以猜到,我对的答案是什么时候全局变量好?是“从不”。什么是你的?
答案 2 :(得分:2)
生成一系列随机数 - 随机生成器应该是唯一的,不能为每次使用实例化。有人可能希望将其实现为线程级单例;但是,在这种情况下,整个过程的单例仍然是合适的。
答案 3 :(得分:1)
系统附带了一个设备/硬件,为了正确使用它,需要一个中央控制点。
答案 4 :(得分:1)
记录日志。
查找本地化字符串资源,例如Strings.get("CONFIRM_DELETE")
。
这两件事都不是应该在对象的公共界面中公开的细节,因此在这里使用单例是有意义的。
答案 5 :(得分:1)
我仍然认为应该避免单身人士(至少在Java中)。
要考虑两个不同的事项:概念和机制用于强制执行Singleton模式。
Singletons的概念有很多用途,日志记录,配置,更不用说当你正在工作的域实际上只有一个实例而你希望对其进行建模时。即一家公司只有一个费用处理办公室,并向无效的办公室发送费用表格是错误的,办公室实际上是一个单身人士。单身人士的概念有许多合法用途。
但是,它通常是导致问题的机制。在Java中,我们通过声明构造函数private
强制执行无法构造的对象,问题是我们还必须通过具体类为实例提供全局访问点 。这会将应用程序中的所有内容与该具体类相结合,这些类在运行时无法更改,或在单元测试中进行模拟。这种机制被认为是邪恶的 - 特别是在可测试性方面。
如果单身人士的概念可以与糟糕的机制分开,那么他们就不会那么邪恶。我可以想到的一个例子是Guice中可用的@Singleton
范围。在Guice的上下文中,它保证了一个实例,但它并没有通过邪恶的私有构造函数/全局访问点机制实现这一点。
答案 6 :(得分:0)
我正在努力摆脱当前正在进行的项目中的Singletons。它们有气味,但有时很难避免。
我的情况是我有一个API,它构建单个对象来处理管理功能,如安全性,配置等.API使用EntityFramework并且还插入了PlugIns(使用MEF)。因为这些类的构造并不总是由我的代码执行(特别是对于EF实体),所以并不总是能够优雅地将它们注入到商业对象中。所以我使用了单身人士,可以在项目范围内的任何地方访问这些单身人士。
答案 7 :(得分:0)
主服务器接收来自客户端的请求,并将这些请求传递给下级进程。从属进程可以使用单例与主服务器通信。
答案 8 :(得分:0)
我尽量不依赖Singleton,但我更喜欢脱钩而不使用Singleton。因此,我经常使用Singleton和Prototype模式,它允许在库加载时注册Prototypes(全局对象构造)。
我正在编写一个由许多库组成的服务器。有许多“通用”库,然后每个服务一个库。 “主”库的任务是查看收到的消息并根据密钥调用正确的服务...这使用简单的std::map
。
使用Singleton作为地图允许我完全解耦代码。没有库取决于我的服务库,我的服务库外的任何代码行都没有注册其服务。实际上,我可以通过在编译时更改我的“链接”命令来决定嵌入哪些服务:如果我没有链接库,则不会嵌入其服务。
我真的觉得它在那里很有用......对于配置而言我更喜欢使用MonoPattern:即看起来正常的类,所有实例共享相同的数据(因此包装一个真正的单例)。因为客户不知道他们正在使用Singleton卧底,所以只是在需要时更容易迁移。
答案 9 :(得分:0)
除了日志记录(正如其他大多数人已经提到的那样),我还使用了单例用于控制反转(IoC)容器。依赖项在应用程序开始时注册一次,并且可以使用单例方法在应用程序期间的任何时间点解析依赖项。
答案 10 :(得分:-1)
它们适合您希望视为独特资源的项目。
作为Web系统中的一个示例,您可能希望仅对所服务的每个页面使用单个数据库连接 - 在这种情况下,使用单例模式是有意义的。 (尽管您必须使用数据库访问对象是单例的知识进行编码,这不太理想,但如果有明确记录,则可以接受。)
答案 11 :(得分:-1)
当程序的一部分需要一个实现特定接口的对象(多态)时,你永远不需要该对象的多个实例。否则静态方法就可以了。