关于设计模式:单身人士有哪些特定的合法用途?

What are some specific legitimate uses for singletons?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
On Design Patterns: When to use the Singleton?

这个问题不在于一般来说,单件物品是否"被认为是有害的"。我只是想从你的经验中知道,在哪些特定的情况下,单身汉似乎工作得很好。

编辑:请,如果你想讨论一下单子的恰当性和/或邪恶性,一般来说,有一个现成的问题:1379751831

哎呀!我刚刚发现我的问题已经在这里被问到了:关于设计模式:何时使用单例?


我们基本上将它们用于两个方面:日志记录和配置。两者都假定应用程序有一个中心配置和一个中心日志文件,并不总是有效的,但在我们的大多数代码中是有效的。我们有时也会将它们用于某些工厂类或缓存类,以确保不会复制密钥元数据。


正在展开我的评论…

这个问题措词不好,单件似乎在许多情况下都能很好地解决。它应该是"在某些特定的情况下,单子不暴露它们的负属性?"简而言之,"什么时候全局变量是好的"?

  • 全局变量是全局变量。

    一旦你使用

    void f()
    {
    X* x = X::getInstance();
    ...
    }

    您点的意大利面已被接受,而不是void f(X*)

  • 单子繁殖,并且喜欢互相依赖。SessionManager使用EventManager使用LogManager。有人希望日志文件提到当前用户的名称。LogManager维护者增加了SessionManager::getInstance()->getUser()->getName();,所有的东西都是玫瑰,直到LoginManager,它也使用LogManager,想要记录一个登录失败。

  • 单子抑制可测试性。

    单实例属性仅在生产代码中半有用。您可能根本无法测试void f()功能,并且可能只有(少数)个测试是为了快乐的道路。

  • 你可以猜到,我对全局变量什么时候好的答案是什么?是"永远"。你的是什么?


    生成一个随机数序列-随机生成器应该是唯一的,而不是为每次使用而实例化。人们可能希望将其作为线程级的单例实现;但是,在这种情况下,整个进程的单例仍然是合适的。


    • 当您的域指定您正在建模的对象只有一个唯一的实例时

    我仍然认为应该避免独生子女(至少在Java中)。

    有两个不同的问题需要考虑:概念和执行单例模式的机制。

    单例的概念有很多用途,比如日志记录、配置,更不用说当您正在工作的域实际上有一些东西,其中只有一个实例,并且您希望对其进行建模。也就是说,一个公司只有一个费用处理办公室,把费用表格发给一个无效的办公室是错误的,办公室实际上是一个单独的办公室。单例概念有许多合法的用途。

    然而,问题通常是由这种机制引起的。在Java中,我们不能通过声明构造器EDCOX1(10)来构造一个对象,问题是,我们还必须通过具体类提供对实例的全局访问点。这将应用程序中的所有内容与具体的类结合在一起,具体的类在运行时是不能更改的,或者在单元测试中是模拟的。这种机制被认为是邪恶的,特别是在可测试性方面。

    如果单子的概念可以从可怜的机制中分离出来,它们就不会那么邪恶了。我能想到的一个例子是,在guice中可用的@Singleton范围。在guice的上下文中,它保证一个实例,但它不能通过邪恶的私有构造函数/全局访问点机制来实现这一点。


    • 登录中。

    • 查找本地化字符串资源,如Strings.get("CONFIRM_DELETE")

    这两者都不是应该在对象的公共接口中公开的细节,所以在这里使用单例是有意义的。


    系统有一个单独的设备/硬件,必须有一个中央控制点才能正确使用。


    除了日志记录(正如大多数其他人已经提到的那样),我还使用了单例来反转控制(IOC)容器。依赖项在应用程序开始时注册一次,并且可以使用singleton方法在应用程序期间的任何时间点解析依赖项。


    我尽量不依赖单例,但是我更喜欢去耦而不是不使用单例。因此,我经常将singleton与原型模式结合使用,这允许在库加载时注册原型(全局对象构造)。

    我正在编写一个由多个库组成的服务器。有许多"公共"库,然后每个服务一个库。"主"库的任务是查看接收到的消息,并根据密钥调用正确的服务…这使用一个简单的std::map

    使用一个单例映射允许我拥有完全分离的代码。没有一个库依赖于我的服务库,没有一行代码在我的服务库之外负责注册它的服务。实际上,我可以通过在编译时修改我的"link"命令来决定嵌入哪些服务:如果我没有链接到库,那么它的服务就不会嵌入。

    我真的觉得这很有用…对于配置和类似的配置,我更喜欢使用单模式:即所有实例共享相同数据(从而包装一个真正的单模式)的普通类。这样可以更容易地进行迁移,以防客户不知道他们使用的是单人卧底。


    主服务器接收来自客户机的请求,并将这些请求传递给一个下级进程。从属进程可以使用单例来与主服务器通信。


    我只是努力工作,在我正在做的这个项目中摆脱了单身汉。它们有气味,但有时很难避免。

    我的情况是,我有一个API,它构建了用于处理管理功能(如安全性、配置等)的单例对象。该API使用EntityFramework,还拉入了插件(使用MEF)。因为这些类的构造并不总是由我的代码(尤其是EF实体)执行的,所以不可能总是将它们优雅地注入到biz对象中。所以我使用了单例,它可以在项目主体的范围内的任何地方访问。


    当程序的一部分需要一个实现特定接口(多态性方面)的对象时,您永远不需要该对象的多个实例。否则静态方法就可以了。


    它们适用于您希望将其视为唯一资源的项目。

    作为Web系统中的一个例子,您可能希望只对所服务的每个页面使用一个数据库连接——在本例中,使用singleton模式是有意义的。(尽管您必须知道数据库访问对象是单例的,这不太理想,但如果有明确的文档记录,则可以接受,等等。)